python生成器和迭代器区别

本文深入解析Python中的迭代器与生成器概念,包括它们的基本原理、创建方法及应用场景,对比迭代器与列表的区别,并详细介绍生成器函数与生成器表达式的使用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、迭代器/生成器基本概念

1.1 什么是迭代器

迭代器(Iterator) 是同时实现__iter__() 与 __next__() 方法的对象。

1.2 什么是生成器

Python 中,提供了两种 生成器(Generator) ,一种是生成器函数,另一种是生成器表达式

  • 生成器函数:包含yeild的函数称为生成器函数
  • 生成器表达式:与列表推导式类似,区别是使用()进行包裹   例:(i for i in range(10))

 二、可迭代对象/迭代器

2.1 可迭代对象

可以直接作用于for循环的对象称为可迭代对象,可迭代对象主要分两类

  1. 一类是集合数据类型和迭代器,如listtupledictsetstr 和实现了__next__方法的类对象
  2. 一类是generator,包括生成器和带yield的generator function。

可以使用isinstance()来判断一个对象是否为可迭代对象

>>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False

2.2 迭代器

Iterator:任何实现了 __next__ 方法 (python2 是 next)的对象都可以称为迭代器

 可以使用isinstance()判断一个对象是否是Iterator对象:

>>> from typing import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('abc', Iterator)
False

生成器都是 Iterator(迭代器),但 list,tuple,dict,str,set 等虽然是Iterabel(可迭代对象),但不是Iterator(迭代器)

2.3 通过iter()方法把可迭代对象转换成迭代器

>>> from typing import Iterator
>>> str_iterator = iter("duozan")
>>> isinstance(str_iterator, Iterator)
True
>>> next(str_iterator)
d

问: 为什么 list,tuple,dict不是迭代器呢?

答: 因为在Python里面 迭代器代表的是一个数据流,迭代器对象可以调用next()方法返回下一个值,而list,tuple,dict无法调用next()方法返回下一个值。(本质为list,tuple,dict只有__iter__魔法方法,没有实现__next__魔法方法)

2.4 创建迭代器

通过实现__iter__() 和 __next__()方法实现一个迭代器

from typing import Iterator


class Fib:
    def __init__(self, n):
        self.prev = 1
        self.cur = 2
        self.n = n

    def __iter__(self):
        return self

    def __next__(self):
        if self.n > 0:
            value = self.cur
            self.cur = self.cur + self.prev
            self.prev = value
            self.n -= 1
            return value
        else:
            raise StopIteration()


f = Fib(10) //f 是一个迭代器
print(type(f),isinstance(f,Iterator))
print([i for i in f])

输出结果: 

可以看到通过Fib类创建的对象是一个迭代器,可以用于循环操作

 2.5 迭代器和列表的区别

它与列表的区别在于,构建迭代器的时候,不像列表把所有元素一次性加载到内存,而是以一种延迟计算(lazy evaluation)方式返回元素,这正是它的优点。比如列表含有中一千万个整数,需要占超过400M的内存,而迭代器只需要几十个字节的空间。因为它并没有把所有元素装载到内存中,而是等到调用 next 方法时候才返回该元素(按需调用 call by need 的方式,本质上 for 循环就是不断地调用迭代器的next方法)。

三、生成器表达式/生成器函数

3.1 通过列表生成式创建生成器

我们可以将列表生成式的中括号改成小括号就创建了一个生成器

list = [i for i in range(10)]
print(type(list))  # <class 'list'>
gen = (i for i in range(10))
print(type(gen))  # <class 'generator'>

3.2 通过函数创建生成器

带有yield的函数称为函数生成器

下面通过代码实现一个斐波那契数列(除第1个,第2个数外,其他的数都是前两个数相加)  eg: 1, 2, 3, 5, 8, 13, 21, 34, 55, …

斐波那契数列代码:

# 实现100以内的斐波那契数

def fib(max):
    a, b = 1, 2
    n = 0  # 斐波那契数
    print(str(a) + "\n" + str(b))
    while n < max:
        n = a + b
        a = b    #把b的旧值传给a
        b = n    #把相加之后的值传给新的b值
        yield n  # 程序走到这里就会暂停下来,返回n到函数外,等下一次调用next()的时候继续执行

for i in fib(100):
    print(i)

运行结果:

1
2
3
5
8
13
21
34
55
89
144

这里非常有必要说一下带有yeild 关键字的生成器函数的执行流程,当调用一次next()的时候,生成器就会执行,碰到yield会先把值返回给外部(这里返回到的其实是i,然后print(i)打印的就是相加之后的值),当再次调用的时候,生成器会从上次中断的地方继续执行。

3.3 取出生成器里面的元素

1.通过调用next()方法取出

gen = (i for i in range(10))
gen.next()

2.通过使用for循环取出

gen = (i for i in range(10))
for i in gen:
    print(i)

四、可迭代对象、迭代器、生成器小结

 

可迭代对象:实现了__iter__魔法方法 ,通过isinstance()判断是否为可迭代对象

迭代器:实现了__iter__ 和 __next__魔法方法

生成器:  Python中含有两种生成器,生成器函数和生成器表达式

  • 生成器函数:包含yeild的函数称为生成器函数
  • 生成器表达式:与列表推导式类似,区别是使用()进行包裹   例:(i for i in range(10))

参考链接:

1.11 Python 中的可迭代对象、迭代器与生成器 — 可乐python说 1.0.0 文档

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值