generator 生成器
说实话,generator这个名字起得不好,语义过于宽泛,极易混淆。
我们这里说的生成器,是一种可以通过附加方法一步一步执行内部逻辑的对象,并且我们还要讨论生成这个对象的一种特殊的函数:生成器函数;
从上面这段我理解的话中,不难看出,对初学者来说,生成器不是一个很好理解的概念,但它很重要。
生成器函数
首先我们来学习生成器函数, 先来看一个普通函数:
def PowTwoGen(max = 0):
n = 0
x=[]
while n < max:
x.append(2**n)
n += 1
return x
r = PowTwoGen(6)
print (r)
[1, 2, 4, 8, 16, 32]
复制代码
这是一个实现了返回一个2的指数list的函数;
现在我们来把它改造成为生成器函数:
def PowTwo(max = 0):
n = 0
while n < max:
yield 2**n
n += 1
r = PowTwo(6)
print (r)
<generator object PowTwo at 0x7f2e94d7b360>
复制代码
注意,我们把return去掉了,用来接元素的x List去掉了,在接元素的位置换成了 yield,你现在看不懂的话,不用慌,讲到关键位置了。
首先,如果你在函数体内用了yield这个关键字,那么它就是一个generator函数了,一个generator函数不会返回实际的数据结果,它只会返回一个generator对象,我们平时说的generator就是指的这个generator对象。
现在关键在这个generator对象上,如果你懂它怎么使用和有什么用处,你就知道用来生成它的generator函数的意思了。
generator对象
def PowTwoGen(max = 0):
n = 0
while n < max:
yield 2**n
n += 1
r = PowTwoGen(6)
print (r)
output = next(r)
print(output)
output = next(r)
print(output)
output = next(r)
print(output)
output = next(r)
print(output)
output = next(r)
print(output)
output = next(r)
print(output)
<generator object PowTwoGen at 0x7fcf837b2360>
1
2
4
8
16
32
复制代码
<generator object PowTwoGen at 0x7fcf837b2360> 表示r是一个generator对象,这个对象存在内存中的0x7fcf837b2360这个地址,但是它并不包含任何数据,它只存了算法,如果你要取数据,需要用next()方法;用一次next()它取一个结果出来,这样表明,generator对象是一种可循环体。
这就很有意思了,你运行PowTwo普通函数的时候,它会立即返回你一个List,这很好,但是这结果会占用内存,比如10万个元素就很尴尬,而PowTwoGen generator函数返回的是一个generator对象,它只占用一个对象所需要的内存空间,但是这个对象代表了取10万个元素的算法,你可以不一次性取出来,要的时候再去拿。
当然,next()这个方法很傻,我们一般用for in 去获取generator对象中的元素:
def PowTwoGen(max = 0):
n = 0
while n < max:
yield 2**n
n += 1
r = PowTwoGen(6)
print (r)
output = []
for i in r:
if i >4:
output.append(i)
print(output)
<generator object PowTwoGen at 0x7f296ff62360>
[8, 16, 32]
复制代码
你看相对于 [1, 2, 4, 8, 16, 32],我们可以灵活取出[8, 16, 32],存储减少了不少,是不是感觉又灵活,又划算呢?
生成一个generator对象,不一定非得用generator函数,还可以这样:
g = (x for x in range(10))
print(next(g))
0
复制代码
把列表生成器的[]改成(),就可以生成generator对象了。
本文地址:http://larabase.com/collection/6/post/187
如果你希望跟我一起学习更多关于Python的知识,欢迎访问我的小站http://larabase.com