侧边栏壁纸
博主头像
AngYi 博主等级

行动起来,活在当下

  • 累计撰写 68 篇文章
  • 累计创建 28 个标签
  • 累计收到 24 条评论

目 录CONTENT

文章目录

Python 迭代器、生成器

AngYi
2022-04-04 / 0 评论 / 0 点赞 / 226 阅读 / 0 字

for 过程中到底发生了什么?


for item in xxxx:
    print(item)
    
  1. 检查该对象是否是可迭代对象isinstance(obj,Iterable)
  2. 在第一步成立的前提下,调用iter函数得到obj对象的__iter__()方法的返回值
  3. iter()方法的返回值,是一个 迭代器
from collections.abc import Iterator,Iterable

class Mylist():
    def __init__(self):
        self.mylist = []

    def add(self, item):
        self.mylist.append(item)
        self.myidx = 0


    # 该对象是可迭代对象的基础是 对象里面有 __iter__()方法

    def __iter__(self):
        return self  #  必须返回一个迭代器,即实现了__iter__和__next__的类

    def __next__(self):
        if self.myidx < len(self.mylist):
            res = self.mylist[self.myidx]
            self.myidx += 1
            return res
        else:
            raise StopIteration

if __name__ == '__main__':
    mylist = Mylist()
    mylist.add(1)
    mylist.add(2)
    mylist.add(3)

    print(isinstance(mylist, Iterable)) # 是否实现__iter__方法
    print(isinstance(mylist, Iterator)) # 想要是一个迭代器,__iter__方法必须返回一个迭代器
                                        # 而这个迭代器里面 必须实现__next__方法和__iter__方法

    # 也就是说实现__iter__方法只能保证它是一个可迭代对象
    # 而__next__方法在__iter__方法实现的前提下,使得对象成为 迭代器,且for 返回的值就是 next方法的返回值
    for item in mylist:
        print(item)

迭代器的应用

比如有个很大的数据,我们不想一次性都读入内存,内存不够,而是想要实现用一条,读一条。这里迭代器就会发挥很大的作用。
比如Pytorch的自定义数据集,就是利用了迭代器的原理。

生成器

如果一个函数中有yield语句,那这个函数就是一个生成器模版。
yield可以理解为会将程序暂停,然后返回yield后面的值,下次运行继续向后

图片.png

所以说用yield 返回a 与range(1,1000)相比,它不会直接生成1-10000,而是用一个生成一个。
迭代器的核心就是,它保存的是生成数据的方式,不是直接生成的数据。生成器yield也是这样,可以让函数暂停执行,返回你想要的数据,再次运行的时候仍然保持上次的状态。

利用yield暂停程序的原理,可以实现并发多任务
图片.png
两个函数交替执行,实现并发;

import time 

def dancing():
    while True:
        print("dancing.....")
        time.sleep(1)
        yield
        

def singing():
    while True:
        print("singing.....")
        time.sleep(1)
        yield
        

def main():
    d = dancing()
    s = singing()
    while True:
        next(d)
        next(s)

if __name__ == '__main__':
    main()
0

评论区