微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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的函数
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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐