没有用过的东西,没有深刻理解的东西很难保证自己会,而且一旦被人问起就支支吾吾不知从何说起。这是很多新手学习Python过程中会遇到的问题(当然包括本菜鸟)。本文主要介绍一下python中的生成器和yield关键词。
首先需要说明一下python中的迭代器(iterator)与生成器(constructor)。
一、迭代器
python中可以直接作用于for循环的对象,比如:列表、元祖、字典、集合、字符串等统称为可迭代对象。迭代器是一个实现了迭代器协议的对象,其可以调用next()方法得到下一个结果,在结果末尾调用会产生Stopiteration。此类对象可以使用for 或其他遍历工具进行迭代。最常见的range()就是一个迭代器,好处是每次只从对象中读取一条数据,不会造成内存的过大开销。可以使用isinstance()判断一个对象是否是Iterator对象。
二、生成器
生成器是与迭代器协议相关的,而且生成器都是迭代器。它是python中一种一边循环一边计算的机制,可以节省大量空间。
创建生成器有两种方法,一种是类似列表生成式的,只需要将[]改为()即可。另外就是使用yield关键词,我们主要说一下第二种方法。
举个简单的例子,打印斐波拉契数列。正常写法如下:
def fib(num):
n, a, b = 0, 0, 1
while n < num:
print(b)
a, b = b, a + b
n += 1
return 'done!'
我们只需要简单的将print改为yield,就将原函数变成了生成器函数。
def fib(num):
n, a, b = 0, 0, 1
while n < num:
yield b
a, b = b, a + b
n += 1
return 'done!'
此时我们得到的函数是一个生成器,可以调用next方法得到结果。一般我们使用for循环对其进行遍历。生成器在执行过程中,遇到yield就中断,下次又继续执行。
小练习
杨辉三角定义如下:
1
/ \
1 1
/ \ / \
1 2 1
/ \ / \ / \
1 3 3 1
/ \ / \ / \ / \
1 4 6 4 1
/ \ / \ / \ / \ / \
1 5 10 10 5 1
把每一行看做一个list,试写一个generator,不断输出下一行的list
def triangles():
res = [1]
while True:
yield res
res = [1] + [t[i]+t[i+1] for i in range(len(res)-1)] + [1]