迭代器,生成器,可迭代对象

时间:2021-10-14
本文章向大家介绍迭代器,生成器,可迭代对象,主要包括迭代器,生成器,可迭代对象使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

迭代器,生成器

迭代器

一个类,如果实现:

  1. 实现 __iter__(self) 方法,并返回自身 self
  2. 实现 __next__(self) 方法,返回迭代的值。

举例:

from collections.abc import Iterator,Iterable

class it(object):
    def __init__(self, num):
        self.num = num

    def __iter__(self):
        return self

    def __next__(self):
        self.num += 1
        # 大于10,抛出异常
        if self.num > 10:
            raise StopIteration
        return self.num

ge = it(1)
print(isinstance(ge,Iterable))
print(isinstance(ge,Iterator))

可迭代对象

实现了 __iter__(self), 返回一个迭代器,就是一个可迭代对象。

iter() 可以将一个可迭代对象转变成一个迭代器。

from collections.abc import Iterator,Iterable

class it(object):

    def __iter__(self):
        return iter([1,2,3])

ge = it(1)
print(isinstance(ge,Iterable))
print(isinstance(ge,Iterator))

生成器

使用 yield 关键字,可以实现生成器, 而且可以直接使用 next()

class generator(object):
    def __init__(self, num):
        self.num = num

    def __iter__(self):
        while self.num < 10:
            yield self.num
            self.num += 1

ge = generator(1)
print(type(ge))
print(isinstance(ge,Iterable))
print(isinstance(ge,Iterator))

当然,上面是一个生成器类,其实生成器跟 __iter__() 没啥太大关系,只要随便使用一个函数,使用 yield 关键字就行了:

def generator():
    yield 1
    
g = generator()
print(g)

生成器的 next(), send(), yield from

next(generator) 很简单,就是不停的执行从当前代码,执行到下一个 yield 处,返回当前 yield 的数据

send(msg) 可以给生成器发送数据,进行数据交互,然后执行到下一个 yield 处,返回 yield 的数据。如果没有可以用来接收数据的变量,则和 next(generator) 效果一样。生成器没有启动时,第一次使用 send() ,必须先发送一个 send(None) ,因为此时还没有 yield 表达式可以来接收值。

yield from <generator> 它可以让两个生成器交互。可以从当前生成器,进入到另一个生成器执行,执行完毕后,再回到当前生成器。

def inner():
    print('enter inner')
    value = yield 2  # 第二次截止到: yield 2 ;  # 第三次从赋值开始: value = send传递过来的值
    print('inner value:',value)
    yield 3  # 第三次完毕
    return 'inner_return'  # 第四次开始

def outer():
    print('outer entered')
    yield 1   # 第一次截至到这里

    value = yield from inner()  # 第二次起始:进入另一个生成器

    yield 4  # 第四次结束
    print('back to outer')  # 第五次开始
    print('value is :', value)  # 第五次结束,并抛出 StopIteration 异常

o = outer()
print(next(o))  # 没啥好说的,往下走
print(next(o))  # 没啥好说的,往下走到 yield 2
print(next(o))  # 没法发送数据,所以 yield 2 前面的 value 会是 None
print(next(o))  # 没啥好说的,不停的往下走
print(next(o))  # 没啥好说的,不停的往下走

# ==================================================
o = outer()
print(o.send(None))  # o.send(None) 等同于 next(o),第一次必须发送 None,先走到 yield 代码处
print(o.send('HH'))  # 尽管发了一个数据:HH,但是第1次 yield 1 前面没有接收这个数据的变量,所以直接走向下一个 yield
print(o.send('HHH'))  # 上一次 yield 停止的地方:value = yield 2 有个变量可以接收值,所以给 value 赋值,然后走到下一个 yield 处
print(o.send('HHHH'))
print(o.send('HHHHH'))

for 循环

for 循环,可以循环迭代器,生成器,可迭代对象。它的原理,就是先执行要循环的对象的__iter__() 方法,获得一个迭代器,然后执行迭代器的 __next__() 方法,并且在循环完毕时,处理一下 StopIteration 异常。虽然我们写函数式的生成器时没有__iter__() 方法,但是它已经内置了这个方法。

譬如:

def it():
    yield 1

ge = it()
print(dir(ge))
i = ge.__iter__()
print(dir(i))
print(next(i))

class it(object):
    def __iter__(self):
        return iter([1,2,3])

# ------- for --------
for i in it():
    print(i)

# ------- 原理 --------
i = it().__iter__()
while True:
    try:
        print(next(i))
    except StopIteration:
        break

原文地址:https://www.cnblogs.com/wztshine/p/15405377.html