python中的yield与yield from
生成器与迭代器
在Python中,迭代器就是可以用来迭代(比如for循环中的迭代)操作的对象,任何实现了__next__
方法的对象都可以称之为迭代器。
class Fib:
def __init__(self, n) -> None:
self.prev = 0
self.cur = 1
self.n = n
def __next__(self):
if (self.n > 0):
value = self.cur
self.cur = self.cur + self.prev
self.prev = value
self.n -= 1
return value
else:
raise StopIteration()
def __iter__(self):
return self
f = Fib(10)
print(next(f))
print(next(f))
print([i for i in f])
"""
1
1
[2, 3, 5, 8, 13, 21, 34, 55]
"""
虽然写了好几行代码只是生成了一个列表,但迭代器的优势在于:不用将所有可能用到的数据都加载到内存中,而是通过next
方法返回特定的元素,也不用保存之前遍历过的元素。在一些特定的场景下,迭代器可以节省大量的内存。
生成器与迭代器的作用相似,但在用法上更加简洁。在python中,使用了yield
关键字的函数会成为生成器函数。函数执行到yield
语句后会立即返回,这一点和return
的行为一样。不同之处在于:下一次调用该函数的时候,会从yield
语句后面接着继续执行。
def fib(n):
prev, curr = 0, 1
while n > 0:
n -= 1
yield curr
prev, curr = curr, curr + prev
f = fib(10)
print(next(f))
print(next(f))
print([i for i in f])
"""
1
1
[2, 3, 5, 8, 13, 21, 34, 55]
"""
使用yield from
的关键字也会成为生成器,不过它会将自己的部分任务交给另一个生成器完成。
def func(n):
print('let\'s go')
yield from fib(n - 1)
yield 55
def fib(n):
prev, curr = 0, 1
while n > 0:
n -= 1
yield curr
prev, curr = curr, curr + prev
print([i for i in func(10)])
"""
let's go
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
"""
注意:使用'yield from'时,控制权会转移到子生成器,并直接从子生成器中获取值,知道子生成器完成迭代。