Python 迭代器与生成器

参考资料: 

几分钟听懂迭代器 【哔哩哔哩教程】 (迭代器讲的很好)

Python迭代器与生成器介绍及在Pytorch源码中应用

Python 迭代器深入讲解 |【AsyncIO从入门到放弃#1】 (生成器讲得很好)

Python进阶 | 五分钟带你弄懂迭代器与生成器

 

迭代器

在python中,如果一个对象有__iter__和__next__方法,那么这个对象就是一个迭代器。

我们也可以调用__iter__函数把可迭代对象变为迭代器。

可迭代对象只有__iter__方法,没有__next__方法。

迭代器既有__iter__方法,也有__next__方法。(这也是迭代器协议所规定的)

在python中,这种前后都有双下划线的方法,既可以用 对象.__iter__() 来调用,也可以直接 iter(对象) 来调用。

 

对于一个for循环中的迭代,中间过程发生了两件事:

  1. __iter__函数把可迭代对象变为迭代器;
  2. 调用迭代器的__next__函数,返回一个元素。

 

我们自己创建一个简单的迭代器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Iterator_test():
    def __init__(self, data):
        self.data = data
        self.length = len(data)
        self.index = 0
     
    def __iter__(self):
        return self
     
    def __next__(self):
        if self.index < self.length:
            self.index += 1
            return self.data[self.index-1]
        else:
            raise StopIteration
 
case = Iterator_test([1, 2, 3])
 
# ========= 用循环的方式获取每一次迭代返回的值 ===========
# for num in case:
#     print(num)   # 输出:1 2 3
 
 
# ========= 调用iter方法获取每一次迭代返回的值 ===========
print(next(case))       # 输出:1
print(next(case))       # 输出:2
print(case.__next__())  # 输出:3
print(next(case))       # 输出:报错,StopIteration的错误

 

生成器

通常,我们把含有yield的函数称之为生成器函数generator function,把调用生成器函数返回的结果称为生成器generator (或者称为生成器对象)。

生成器是迭代器,不同的是生成器的实现更简洁。

 

__next__函数是由yield控制的。

return的作用是触发StopIteration异常。

生成器示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def count(start=0, step=1, end=8):
    n = start
    while n < end:
        yield n     
        n += step
 
if __name__ == '__main__':
    c = count(end=5)   # c是生成器
 
    # # ===== 用next函数来返回值
    # print(next(c))   # 输出 0
    # print(next(c))   # 输出 1
 
    # ===== 用for循环来返回值,for循环实际上也是会调用next函数
    for i in c:
        print(i, end=' ')   # 输出:0 1 2 3 4

 

 

总结一下yield的作用:

  1. 把函数变为生成器函数;
  2. 当程序运行到yield语句这里时,yield语句右边的对象作为next()的返回值;
  3. 返回一个值之后,程序会在yield语句这里暂停,当再次使用next()函数时,程序从该位置继续运行。

class实现的迭代器和yield实现的迭代器比较:

 

posted @   Picassooo  阅读(491)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示