Python上手攻略-高级特性-generator

本文深入浅出地介绍了Python中的生成器概念,包括生成器函数如何通过yield关键字逐步执行内部逻辑,以及生成器对象如何实现按需获取数据,有效节省内存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值