zoukankan      html  css  js  c++  java
  • python 可迭代对象,迭代器,生成器的区别及使用

    可迭代对象

    可迭代对象类型:list,dict,tuple,str,set,deque等

    如何判断一个对象是否是可迭代对象,可以通过dir()方法看它里面有没有__iter__方法,如果有这个方法就是可迭代对象。

    迭代器对象

    上述的可迭代对象类型都不是迭代器,那什么是迭代器?

    迭代器对象相对可迭代对象无非就是多了个__next__方法。
    所以迭代器是在可迭代的基础上实现的。要创建一个迭代器,我们首先得有一个可迭代对象。

    现在就来看看,如何创建一个可迭代对象,并以可迭代对象为基础创建一个迭代器。

    from collections.abc import Iterable, Iterator, Generator
    
    class Aiterable(object):
        def __init__(self, num):
            self.start = num
    
        def __iter__(self):
            return Aiterator(self.start)  # 返回一个迭代器
    
    
    class Aiterator(object):
        def __init__(self, start):
            self.start = start
    
        def __iter__(self):
            return self
    
        def __next__(self):
            if self.start > 0:
                self.start = self.start-1
                return self.start
            raise StopIteration
    
    
    if __name__ == '__main__':
        a = Aiterable(5)
        print(isinstance(a,Iterable))  # True
        print(isinstance(a,Iterator))  # False
        t = Aiterator(5)
        print(isinstance(t,Iterator))  # True  正式因为Aiterator里面有__next__方法
        iter = iter(a)
        print(isinstance(iter,Iterator))  # True
        print(iter.__next__())
        print(iter.__next__())
        print(iter.__next__())
        print(iter.__next__())
    

    for循环的过程就是将可迭代对象转换为迭代器对象,再不断调用__next__方法

    生成器

    生成器是在迭代器的基础上,再实现了yield

    生成器的创建方式有两种

    • 列表生成式
    L = (x*x for x in range(10))
    print(isinstance(L,Generator))  # True
    
    • 实现yield函数
    # 实现了yield的函数
    def mygen(n):
        now = 0
        while now < n:
            yield now
            now += 1
    
    if __name__ == '__main__':
        gen = mygen(10)
        print(isinstance(gen, Generator))  # True
    
    

    生成器的激活/运行方式有两种

    • 使用next()
    • 使用gengerator.send(None)

    示例:

    def mygen(n):
        now = 0
        while now < n:
            yield now
            now += 1
    
    if __name__ == '__main__':
        gen = mygen(4)
    
        # 通过交替执行,来说明这两种方法是等价的。
        print(gen.send(None))
        print(next(gen))
        print(gen.send(None))
        print(next(gen))
    

    生成器的执行状态

    • GEN_CREATED 等待开始执行
    • GEN_RUNNING 解释器正在执行(只有在多线程应用中才能看到这个状态)
    • GEN_SUSPENDED 在yield表达式处暂停
    • GEN_CLOSED 执行结束

    示例:

    from inspect import getgeneratorstate
    
    def mygen(n):
        nums = 0
        while nums < n:
            yield nums
            nums += 1
        raise StopIteration  # 注意自己编写生成器时要在结束时抛stop异常
    
    if __name__ == '__main__':
        gen = mygen(2)
        print(getgeneratorstate(gen))
    
        print(next(gen))
        print(getgeneratorstate(gen))
    
        print(next(gen))
        gen.close()  # 手动关闭/结束生成器
        print(getgeneratorstate(gen))
    

    向生成器发送消息

    def mygen(n):
        nums = 0
        while nums < n:
            # rec = yield可以接收外部程序通过send()发送的信息,并赋值给rec
            rec = yield nums   # yield nums是将nums  return给外部调用程序。
            if rec is None:
                rec = 1
            nums += rec
        raise StopIteration
    
    if __name__=="__main__":
        gen = mygen(10)
        print(next(gen))  # 【坑】注意第一次一定要next或者send(None)来启动
        print(gen.send(2))
        print(next(gen))
        print(gen.send(4))
    
    # 输出
    0
    2
    3
    7
    
  • 相关阅读:
    原来 Sql Server 的存储过程是可以调试的
    网站SEO优化之如何发布外链
    7个有助于SEO优化的网站文章编辑技巧
    技术峰会2005
    SHA1算法告破
    Google Suggest
    Photo Story 3 for Windows XP
    SQL Server 2005: 价格和开源
    抱歉,昨天加班未能参加讨论
    2GB Hotmail comes!
  • 原文地址:https://www.cnblogs.com/FuckSpider/p/11557257.html
Copyright © 2011-2022 走看看