Python中的Iterator和Generator

Iterator

Iterator 是Python 中用于 for in 的一种类型,如果要将对象实现为Iterator,该对象需要实现两个魔法方法__iter____next__

__iter__

该方法在Iterator 初始化的时候被调用,用于返回一个可以迭代的对象,该对象需要实现__next__方法。

__next__

该方法每次应该返回迭代的下一个值,并且在迭代结束时,抛出异常 StopIteration 表示迭代结束。

示例

如下的Fib类被实例化后,可以用于 for in 中迭代斐波纳切数列。

class Fib:
    def __init__(self, lim: int = 100):
        self.pre_num = 1
        self.cur_num = 1
        self.lim = lim

    def __iter__(self):
        return self

    def __next__(self):
        self.pre_num, self.cur_num = self.cur_num, self.cur_num + self.pre_num
        if self.pre_num > self.lim:
            raise StopIteration
        return self.pre_num


fib = Fib()
for each in fib:
    print(each)¡

Generator

Generator function

函数体内包含有 yield 关键字的函数将被视为 generator function,当它想要返回一个结果时,使用 yield 而不是 return。此时,函数将会被Python Frame挂起,并将返回前的状态保存下来。等下一次该函数再被调用时,Frame将恢复挂起的状态并继续执行。示例如下:

def fib(limit):
    a, b = 0, 1
    while a < limit:
        yield a
        a, b = b, a + b

Gernerator object

当有如下执行语句时,generator function 的返回值不是结果,而是一个generator 对象。

# "fib" implementation refers to above one.
f = fib(100)
for each in f:
    print(each)

该对象和 Iterator 类似,可以用 for in 语句来进行迭代,结束也会抛出异常 StopIteration表示迭代终止。

Generator expression

使用Generator 表达式可以生成一个匿名的Generator function,语法就是将列表推导式的中括号变为小括号。如下:

# Output: <generator object <genexpr> at 0x0000000002EBDAF8>
(x**2 for x in my_list)

不像列表推导式会直接返回一个列表,生成器表达式仍然遵循生成器的规则,每次 next 返回一个结果。该表达式还可以作为函数的传入参数,此时可以省去表达式两端的小括号,如下:

# Output: 146
sum(x**2 for x in my_list)

Generator优势

实现简洁

相较于Iterator,生成器的__iter__, __next__方法和 StopIteration 异常都由Python隐式地生成。

内存高效

普通的函数在返回一个序列前,需要将完整的序列保存到内存中。如果一个序列包含了大量的items,将会造成严重的内存占用。而生成器每次只产生一个item。

表示无限序列

无限的序列无法用容器存放,但可以用Generator来表示。

流水线

通过流水线可以获得更高的可读性和效率,例如:


with open('sells.log') as file:

    pizza_col = (line[3] for line in file)

    per_hour = (int(x) for x in pizza_col if x != 'N/A')

    print("Total pizzas sold = ",sum(per_hour))

Reference

<think>好的,我现在需要回答用户关于Python生成器generator迭代器iterator)的区别联系的问题。首先,我得回顾一下自己对这些概念的理解,确保正确性。 首先,迭代器Iterator)是Python中用于迭代的对象,遵循迭代器协议,即必须实现__iter__()__next__()方法。每次调用next()时会返回下一个值,直到没有元素时引发StopIteration异常。例如,列表、元组等可迭代对象可以通过iter()函数转换为迭代器生成器Generator)则是一种特殊的迭代器,使用yield语句来生成值。生成器函数在每次调用next()时执行到yield处暂停,保存当前状态,下次继续执行。生成器表达式也是一种创建生成器的方式,类似列表推导式,但使用圆括号。生成器更节省内存,因为它们是惰性求值的,不需要一次性生成所有数据。 接下来,我需要整理它们的区别联系。区别方面,生成器迭代器的一种,但实现方式更简洁,使用yield。生成器只能遍历一次,而迭代器可能支持多次遍历(取决于具体实现)。内存占用上,生成器更高效,尤其处理大数据时。语法上,生成器用函数yield,或者生成器表达式,而迭代器需要定义类并实现__next____iter__方法。 联系方面,两者都用于迭代,都遵循迭代器协议。生成器属于迭代器的子类,所以生成器也是迭代器。使用时都可以通过for循环或next()函数处理。 然后,我需要检查用户提供的引用资料,确保回答符合引用内容。例如,引用[3]提到iter()函数用于从序列生成迭代器,引用[4]说明生成器是另一种迭代器形式。这些需要整合到回答中,正确标注引用。 可能还需要考虑用户可能混淆的点,比如生成器与普通迭代器的创建方式不同,或者生成器的惰性求值特性。同时,提供代码示例帮助理解,如生成器函数生成器表达式的例子,以及自定义迭代器的类示例。 最后,要确保回答结构清晰,分点列出区别联系,使用中文,LaTeX格式正确,引用标识正确放置。然后生成相关问题,可能涉及应用场景、性能比较、创建方式等。</think>### Python生成器迭代器的区别及联系 #### 1. **迭代器Iterator)** - **定义**:迭代器是遵循**迭代器协议**的对象,需实现两个核心方法: - `__iter__()`:返回迭代器自身 - `__next__()`:返回下一个元素,若没有则抛出`StopIteration`异常 例如,使用`iter()`可将列表转为迭代器: ```python lst = [1, 2, 3] it = iter(lst) # 转换为迭代器 print(next(it)) # 输出: 1 [^3] ``` - **特点**: - 支持手动或循环遍历(如`for`循环) - 部分迭代器可重复使用(如文件对象),部分只能遍历一次(如生成器) #### 2. **生成器Generator)** - **定义**:生成器是**通过函数生成值的迭代器**,使用`yield`关键字暂停执行并保留状态: ```python def count_down(n): while n > 0: yield n n -= 1 gen = count_down(3) # 生成器对象 print(next(gen)) # 输出: 3 [^4] ``` 或通过生成器表达式创建: ```python gen_expr = (x**2 for x in range(3)) # 生成器表达式 ``` - **特点**: - **惰性求值**:按需生成值,节省内存 - **一次性遍历**:遍历结束后无法重启 - **简洁语法**:无需显式定义`__iter__``__next__`方法 #### 3. **区别对比** | **特性** | 迭代器 | 生成器 | |-------------------|---------------------------|--------------------------------| | **实现方式** | 需定义类并实现协议方法 | 使用`yield`或生成器表达式 | | **内存占用** | 可能占用较多(存储所有数据) | 惰性计算,内存效率高 | | **复用性** | 部分可复用(如列表迭代器) | 只能遍历一次 | | **语法复杂度** | 较高 | 较低(自动生成协议方法) | #### 4. **联系** - **共同协议**:两者均遵循迭代器协议,可通过`next()`获取值 - **包含关系**:生成器迭代器的子类(所有生成器都是迭代器,反之不成立) - **应用场景**:均用于处理大规模数据流或需要延迟计算的场景[^2] #### 5. **代码示例对比** - **自定义迭代器**: ```python class Squares: def __init__(self, n): self.n = n self.current = 0 def __iter__(self): return self def __next__(self): if self.current >= self.n: raise StopIteration result = self.current ** 2 self.current += 1 return result it = Squares(3) print(list(it)) # 输出: [0, 1, 4] ``` - **生成器实现相同功能**: ```python def squares_gen(n): current = 0 while current < n: yield current ** 2 current += 1 gen = squares_gen(3) print(list(gen)) # 输出: [0, 1, 4] ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值