第一次写博客,排版格式什么的不是很熟悉,so,看内容就好了:)
要说清楚什么是Generator(生成器),就要讲什么是Iterator(迭代器)。
- Iterator(迭代器)和Iterable(可迭代对象)
什么是Iterator(迭代器)呢?Python官方解释如下:
An iterator is an object that implements next, which is expected to return the next element of the iterable object that returned it, and raise a StopIteration exception when no more elements are available.
简单翻译一下:Iterator(迭代器)是一个实现了next 方法的对象,这个 next 方法执行会返回下一个Iterable(可迭代对象)的值,当没有下一个Iterable(可迭代对象)的值可以返回的时候,就抛出 StopIteration 错误。
这个时候我们可以看到,又多了一个概念Iterable(可迭代对象),没关系,我们再看一下Python官方介绍:
An iterable object is an object that implements __iter__, which is expected to return an iterator object.
简单翻译一下:Iterable(可迭代对象)是一个实现了 __iter__ 方法的对象,__iter__ 方法被用来返回Iterator(迭代器)对象。
有点懵圈?举个例子,list(列表)、dict(字典)、tuple(元组)都是Iterable(可迭代对象),但他们不是Iterator(迭代器),因为他们没法实现 next 方法。
还有一个简单的判断方法,可以用于 for 循环的都是Iterable(可迭代对象),可以用于 next 的都是Iterator(迭代器),Iterable(可迭代对象)包含Iterator(迭代器)。
- Generator(生成器)
Generator(生成器)实际上就是Iterator(迭代器)的一种。Python官方介绍如下:
Generator functions allow you to declare a function that behaves like an iterator, i.e. it can be used in a for loop.
简单翻译一下:Generator(生成器) 可用于For 循环,是一种Iterator(迭代器)。
g = (x * x for x in range(10))
g 即是一个简单的Generator(生成器)对象,右边为Generator Expression(生成器表达式),返回Generator(生成器)对象。
def fib():
prev, curr = 0, 1
while True:
yield curr
prev, curr = curr, curr + prev
注意,fib 方法返回用的不是return ,而是yield 。什么是yield 呢?当一个函数使用yield ,第一次执行从函数第一行开始,在yield 处返回,第二次执行时从返回处继续(恢复执行),当执行到yield 时再返回。return则是每次执行都从函数第一行开始执行,当执行到return 时返回。
参考stack overflow高票解析,yield 有一下特性:
- yield 返回一个Generator(生成器);
- 带有yield 的函数被调用时,函数代码并不会马上执行,等到用for 进行迭代时再执行;
- 理解上面恢复执行的概念。
def AddOnePlusThree():
print("Begin.")
while True:
print("Start.")
result = 1 + 3
yield result
print("Restart.")
当执行以下代码时,
a = AddOnePlusThree()
print(a)
next(a)
print('')
next(a)
print('')
next(a)
返回结果如下:
<generator object AddOnePlusThree at 0x03264FC0>
Begin.
Start.
Restart.
Start.
Restart.
Start.
Process finished with exit code 0
请结合恢复执行的概念进行理解。
for循环用来调用yield 返回的生成器的值。
b= AddOnePlusThree()
for item in b:
print('')
print(item)
返回结果如下:
Begin.
Start.
4
Restart.
Start.
4
Restart.
Start.
4
...
...
请结合恢复执行的概念进行理解。
上面的例子可能没什么实际意义,下面实现一个Fibonacci 生成器。
def fibon(n):
a = b = 1
for i in range(n):
yield a
a, b = b, a + b
for x in fibon(10):
print(x)
返回结果如下:
1
1
2
3
5
8
13
21
34
55
Process finished with exit code 0
实际上,n 如果很大时,Fibonacci 生成器的作用才能体现出来,因为生成器是当运行时产生值,而且只能迭代一次,并不像list 那样将所有值全部扔到内存中。
关于Generator(生成器)暂时先讲到这里吧。
以上。