Python - 可迭代对象、迭代器 and 生成器

Python - 可迭代对象、迭代器 and 生成器

  • 可迭代对象

    当一个对象实现了 __iter__() 方法,并返回一个迭代器时,这个对象称为可迭代对象。

    对于一个可迭代对象,for 循环所迭代的目标为 __iter__() 方法返回的对象(迭代器)。

    例如:

    from collections import Iterable
    
    class my_iterable(Iterable):
    
        def __init__(self):
        	# list 是一个列表,是一个可迭代对象,但不是迭代器
            self.names = ['jack', 'tom', 'pure']
    
        def __iter__(self):
        	# 将 list 转换为迭代器,作为 __iter__() 的返回值
            return iter(self.names)
    
    nie = new_iterable()
    print(isinstance(nie, Iterable))
    for i in nie:
        print(i, end=' ')
    

    打印的结果为:

    True
    jack tom pure
    
  • 迭代器

    当一个对象实现了 __next__() 方法时,这个对象称为迭代器。

    迭代器通过调用对象中的 __next__() 方法持续得到下一个元素。

    对于一个迭代器,for 循环所迭代的目标就是迭代器本身,for 循环会持续调用 __next__() 方法,直到 __next__() 方法抛出 StopIteration 异常时停止。

    例如:

    class new_iterator(Iterator):
    
        def __init__(self, names):
            self.index = -1
            self.names = names
    
        def __next__(self):
            self.index += 1
            # 当索引超出 names 索引范围时,表示所有元素迭代完成
            # 此时抛出 异常,for 循环会捕获此异常并结束迭代。
            if self.index >= len(self.names):
                raise StopIteration
            else:
                return self.names[self.index]
    
    nir = new_iterator(['jack', 'tom', 'pure'])
    print(isinstance(nir, Iterator))
    for i in nir:
        print(i)
    
  • 生成器

    如果一个 函数 中包含 yield 关键字时,则此函数称为生成器模板。在调用此生成器模板是会返回一个生成器对象。

    生成器是特殊的迭代器,同样可以使用迭代器进行迭代。在解释器检测到函数中包含 yield 关键字时会帮助其生成 __next__() 方法。

    当程序执行到 yield 时会暂停,当调用生成器的 __next__() 方法时程序继续,并返回 yield 返回的对象 。

    在生成器中,除了 __next__() 方法,还存在 __send__(arg) 方法同样可以使程序继续执行,并且可以向生成器中传递参数 arg

    下面看生成器在 for 循环下运行的例子:

    def gen(end):
        n = 0
    	while n < end:
        	yield n
            n += 1
            if n == 5:
                raise StopIteration
    
    def gen_test():
        g = gen(10)
        for i in g:
            print(i, end=" ")
    

    结果为:

    0 1 2 3 4 
    

    下面看使用 __next__() 方法运行生成器的例子:

    def gen(end):
        n = 0
        while n < end:
            yield n
            n += 1
            if n == 5:
                raise StopIteration
    
    def gen_test():
        g = gen(10)
        n = 0
        while 1:
            n += 1
            try:
                r = next(g)
            except StopIteration:
                print("stop!")
                break
            print(r, end=" ")
    

    下面看使用 __send__() 方法运行生成器的例子:

    def gen(end):
        n = 0
        while n < end:
            r = yield n
            n += 1
            if n == 5:
                print(f"yield 传递的参数 {r}")
                break
        # 生成器在结束时会抛出 StopIteration 异常
        # 生成器模板中 return 的返回值将作为异常的信息抛出。
        return "Error msg: stop!"
    
    
    def gen_test():
        g = gen(10)
        n = 0
        while 1:
            n += 1
            try:
            	# send 方法不能作为迭代的初始,
            	# 因为执行到 yield 时程序暂停, 
            	# send 传递的参数,语句 r = yield n 并没有执行给 r 赋值的操作
            	# send(arg) 没有对象接受 arg 参数,所以会抛出异常。
                if n > 2:
                    r = g.send("Send arg")
                else:
                    r = next(g)
            except StopIteration as si:
                print(si.value)
                break
            print(r)
    

    运行结果为:

    0
    1
    2
    3
    4
    yield 传递的参数 Send arg
    Error msg: stop!
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值