Python理解yiled关键字

一直对Python的yield关键字有点迷糊,今天整理下相关的知识。

迭代的概念

Python是一门极其灵活的语言,其很多数据里都包含了其他类型的元素。而我们在实际使用的时候,经常需要逐个地取出元素。逐个获取元素的过程,就是迭代

Python的 listtuplestring等顺序类型,还包括 dictset等也都是。就是如果我们可以从一个对象中,逐个地获取元素,那么这个对象是「可迭代的」。

至于迭代器则是抽象的一个数据流,是只允许迭代一次的对象。

1
2
for i in range(10):
print(i)

生成器和yield关键字

生成器函数是一种特殊的函数,而生成器则是特殊的迭代器。

1
2
3
4
5
6
7
8
9
10
11
def func():
return 1

def gen():
yield 1

print(type(func)) # <class 'function'>
print(type(gen)) # <class 'function'>

print(type(func())) # <class 'int'>
print(type(gen())) # <class 'generator'>

最重要的差异是二者返回的类型是不一样的,生成器函数返回一个迭代器。

yield

yield关键字仅用户定义生成器函数。与普通函数不同的是,生成器函数是惰性计算的,只有在返回的生成器调用成员方法时,相应函数中的代码才会被执行。

1
2
3
4
5
6
def square():
for x in range(4):
yield x ** 2
square_gen = square()
for x in square_gen:
print(x)

由前面可知,square_gen表示一个迭代器对象,for 循环会调用迭代器对象的 next() 函数,将生成器中的下一个值赋值给 x , 然后再继续循环,直到终止。

yield的好处

节省时间空间上的开销。Python 之所以要提供这样的解决方案,是因为在很多时候,我们只是需要逐个顺序访问容器内的元素。大多数时候,我们不需要一口气获取容器内所有的元素。

实战一下

生成斐波那契数列

1
2
3
4
5
6
7
8
def gen_fib(n_max):
n,a,b = 0,0,1
while n < n_max:
yield b
a , b = b , a+b
n += 1
fib = [x for x in gen_fib(10)]
fib # [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

参考

  1. Python 中的黑暗角落(一):理解 yield 关键字
  2. 廖雪峰的官方网站

感恩 始终 这位大佬,跟着走一遍打了一遍!