Alby's blog

世上没有巧合,只有巧合的假象。

0%

Python 生成器和生成器函数

一、概述

请勿将生成器函数( generator function )和生成器( generator )混淆。其次生成器函数和普通函数有所区别,《Fluent Python》( 《流畅的 Python》 )作者 Luciano Ramalho 甚至觉得应该新增一个 gen 关键字来区分两者。

本文未将函数和方法加以区分。

二、生成器

什么是生成器在此无需多说。生成器可由“生成器函数( generator function )”返回或通过“生成器表达式( gererator expression )”构造。

1、生成器表达式构造生成器

1
2
3
>>> g = (2 * n for n in range(50)
>>> type(g)
generator

顺便说一下,range 对象是可迭代对象但不是迭代器。

1
2
3
4
5
6
7
>>> r = range(50)
>>> type(r)
range
>>> isinstance(r, Iterable)
True
>>> isinstance(r, Iterator)
False

2、生成器函数返回生成器

1
2
3
4
5
6
7
8
9
10
11
def firstn(n):
num = 0
while num < n:
yield num
num += 1

>>> type(firstn)
function
>>> g = firstn(10)
>>> type(g)
generator

顺便说一下,生成器与迭代器和可迭代对象的关系。

生成器也是迭代器。

1
2
3
4
5
>>> from collections import Iterator
>>> type(g)
generator
>>> isinstance(g, Iterator)
True

因为迭代器本身是可迭代对象,所以生成器也是可迭代对象。

1
2
3
>>> from collections import Iterable
>>> isinstance(g, Iterable)
True

三、生成器函数和生成器内省

1、生成器函数内省

生成器函数也是函数。特别地,可通过 inspect.isgeneratorfunction(object) 函数判断函数是普通函数还是生成器函数。

1
2
3
4
5
6
7
>>> firstn
<function __main__.firstn>
>>> type(firstn)
function
>>> import types
>>> types.FunctionType
function

生成器函数是函数。

1
2
3
4
>>> isinstance(firstn, types.FunctionType)
True
>>> import inspect
>>> inspect.isfunction(firstn)

判断对象是否是生成器。

1
2
3
>>> import inspect
>>> inspect.isgeneratorfunction(firstn)
True

当然,生成器函数不是生成器。

1
2
3
4
5
>>> import types
>>> types.GeneratorType
<class 'generator’>
>>> isinstance(firstn, types.GeneratorType)
False

2、生成器内省

调用生成器函数不会生成通常的结果,不会执行函数体的任何代码,函数返回的类型为 generator 的生成器对象。

1
2
3
4
5
>>> g = firstn(10)
>>> g
<generator object firstn at 0x11ea26ba0>
>>> type(g)
generator

判断对象是否是生成器。

1
2
3
4
5
6
7
>>> import types
>>> types.GeneratorType
<class 'generator’>
>>> inspect.isgenerator(g)
True
>>> isinstance(g, types.GeneratorType)
True

当然,生成器不是生成器函数,也不是函数。

1
2
3
4
>>> inspect.isgeneratorfunction(g)
False
>>> inspect.isfunction(g)
False

参考资料