python系列之生成器和迭代器的一些辨析和应用

340 阅读2分钟

1. 相关对比

1.1 可迭代对象和迭代器的对比

1.迭代器只能遍历一次,可迭代对象可以进行多次遍历 2.迭代器只能前进,不能后退 3.迭代器必须在内部同时实现iter方法和next方法,可迭代对象实现了iter方法,不一定会实现next方法

1.2 迭代器和生成器的对比

1.迭代器必须在内部同时实现iter方法和next方法。而生成器是一种特殊的迭代器,内部支持了生成器协议,不需要再明确实现iter方法和next方法,语法上更为简洁

2.生成器是用于生成元素的,迭代器是用于访问元素的

3.生成器是一种特殊的迭代器,迭代器输出生成器的内容

1.3 yield和return的对比

1.3.1 yield

使用了yield关键字的函数就不再是函数,而是生成器。

代码执行到yield会暂停,然后把结果返回回去,下次启动时生成器会在暂停的位置继续往下执行。

每次启动生成器都会返回一个值,多次启动可以返回多个值。

1.3.2 return

只能返回一次值,代码执行到return语句就停止迭代

1.4 迭代器和for循环的区别

迭代器:

迭代器必须同时实现iternext方法。对于迭代器来说,iter返回的是自身self,因此迭代器只能遍历一次。next返回迭代器的下一个元素,没有元素则抛出异常,会暴露给开发者。

For循环:

(1) 当循环对象为迭代器时,调用iter返回自身,调用next方法按顺序返回迭代器中的值,迭代到最后会抛出StopIteration异常

(2) 当循环对象为可迭代对象时,调用iter每次返回一个独立的迭代器(这里与迭代器的iter不同),可以保证不同的迭代过程互不影响,因此可以遍历多次。然后调用next方法按顺序返回迭代器中的值,迭代到最后会抛出StopIteration异常,这个异常不会暴露给开发者

2.综合应用

2.1 反向迭代

2.1.1 reversed()方法

reversed()方法本质上是调用了内部的reversed方法,如果对象内部没有实现reversed方法,则不能使用reversed()方法来完成反向迭代

list1 = ["西安", "上海", "苏州", "郑州", "武汉"]
for city in reversed(list1):
    print(city)

result:

武汉
郑州
苏州
上海
西安

2.1.2 自定义reversed方法

class Sequence:
​
    def __init__(self, n):
        self.n = n
​
    def __iter__(self):
        start = 0
        while start < self.n:
            yield start
            start += 1
​
    def __reversed__(self):
        start = self.n - 1
        while start >= 0:
            yield start
            start -= 1
​
​
sequence = Sequence(5)
for num in sequence:
    print(num)

result:

0
1
2
3
4
for num in reversed(sequence):
    print(num)

result:

4
3
2
1
0
```python系列之生成器和迭代器