迭代器
原理非常类似Lua的泛型for。
for v in shit:
print v
#for的幕后逻辑如下;
iterable = iter(shit) #生成对象的迭代器:iter()内置函数放回一个定义了__next__()方法的迭代对象
v = next(iterable) #进行迭代:next()内置函数会调用__next__方法返回迭代数据。
#当迭代完了,next会抛出StopIteration的异常来终止for循环。
#了解了for的幕后逻辑,我们可以自定义可迭代对象,而不仅限于使用内置类型。
class IterableObj:
"""文档说明字符串"""
def __init__(self, data):
self.data = data
self.index = len(data)
def __iter__(self): #iter(obj)触发并返回值
return self
def __next__(self): #next(obj)触发并返回值
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
obj = IterableObj([1, 2, 3, 4, 5])
for v in obj:
print(v)
#5
#4
#3
#2
#1
生成器:yield
Generator,用于生成迭代器。写法类似函数,但当它们要返回数据时会使用 yield 语句,yield的效果就是每次next(生成器)时,就会从上次离开位置回复执行。
相比于上面手写迭代器,本质上就是自动完成了这些工作:
- 自动创建方法
- iter() 和 next() 方法。
- 保存程序状态
- 类似lua的闭包
- 自动引发stopIteration
所以利用生成器,可以大大简化生成迭代器的工作。
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
for char in reverse('golf'):
print(char)
生成器表达式
类似列表推导式。
sum(i*i for i in range(10)) #285
xvec = [10, 20, 30]
yvec = [7, 5, 3]
sum(x*y for x,y in zip(xvec, yvec)) #260
from math import pi, sin
sine_table = {x: sin(x*pi/180) for x in range(0, 91)}
unique_words = set(word for line in page for word in line.split())
valedictorian = max((student.gpa, student.name) for student in graduates)
data = 'golf'
list(data[i] for i in range(len(data)-1, -1, -1)) #['f', 'l', 'o', 'g']