迭代器
迭代器协议
对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,
要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退)
可迭代对象:实现了迭代器协议的对象
协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象。
字符串,列表…等都可迭代对象,而不是迭代器
只不过使用for循环的时候调用了它们调用了__iter__()
,把他们变成了迭代器
In [8]: a = "abc"
In [9]: a.__iter__()
Out[9]: <str_iterator at 0x1c3cf6abfd0>
In [11]: b = a.__iter__()
In [13]: b.__next__()
Out[13]: 'a'
for循环首先会将让对象调用__iter__()
变成迭代器
遵循迭代器协议
每次遍历得到的值就是 对象.__iter__().__next__()
然后捕捉StopIteration异常,如果遇到这个异常就不继续进行迭代
for循环和索引没有关系
迭代的方式有
g = obj.__next__()
# 或者
g = next(obj)
# 或者
g = obj.send(None) # 这个下面会提到
生成器
python的生成器有两种形式
列表生成式
>>> a = (i for i in range(10)) # a指向的不是一个列表,而是一个生成器
>>> type(a)
<type 'generator'>
生成器是一种迭代器,可以直接调用__next__()
进行迭代
还有一种是 生成器 函数
一般来说,函数中只要有yield就可以看成是一个生成器
生成器函数自动实现迭代器协议
def A():
yield 1
yield 1
yield 1
a = A()
print(type(a)) # <class 'generator'>
print(a.__next__()) # 1
print(a.__next__()) # 1
print(a.__next__()) # 1
第一次迭代,函数会从开始执行到第一个yield结束 并返回值1
第二次迭代,函数会继续执行到第二个yield结束 并返回值1
…
yield是可以 赋值给局部变量的
所赋的值是看obj.send()传的什么值
def A():
x = yield 1
print(x)
yield 2
a = A() # a指向一个生成器
print(a.__next__()) # a进行一次迭代 执行到x = yield 1 并返回值1
print(a.send(222)) # 将222传给x 执行到yield 2 并返回值2
yield可以像return那样返回值
创建生成器之后,生成器迭代一次 函数可以执行到yield位置 继续迭代可以接着执行到下一个yield位置(可以保存状态)
(函数执行到return就直接结束了)