python基础: 生成器,生成器表达式

本文介绍了Python中的迭代器协议,强调了生成器在迭代中的重要作用。通过实例展示了如何将普通函数转化为生成器,利用`yield`关键字实现延迟计算。接着,文章探讨了生成器表达式的使用,作为简化创建生成器的方式,它等价于简洁的生成器函数。最后,给出了使用生成器表达式解决美元硬币组合问题的例子。

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

能以一种一致的方式对序列进行迭代(比如列表中的对象或文件中的行)是Python的一个重要特点。这是通过一种叫做迭代器协议(iterator protocol,它是一种使对象可迭代的通用方式)的方式实现的。比如说,对字典进行迭代可以得到其所有的键:

>>> some_dict={'a':1,'b':2,'c':3}
>>> for key in some_dict:
...     print (key)
... 
a
b
c

当你编写for key in some_dict时,Python解释器首先会尝试从some_dict创建一个迭代器:

>>> dict_iterator=iter(some_dict)
>>> dict_iterator
<dict_keyiterator object at 0x7f1674032048>

迭代器是一种特殊对象,它可以在诸如for循环之类的上下文中向Python解释器输送对象。大部分能接受列表之类的对象的方法也都可以接受任何可迭代对象。比如min、max、sum等内置方法以及list、tuple等类型构造器:

>>> list(dict_iterator)
['a', 'b', 'c']

生成器(generator)是构造新的可迭代对象的一种简单方式。一般的函数执行之后只会返回单个值,而生成器则是以延迟的方式返回一个值序列,即每返回一个值之后暂停,直到下一个值被请求时再继续。要创建一个生成器,只需将函数中的return替换为yield即可:

def squares(n=10):
    for i in range(1,n+1):
        print("Generating squares from 1 to %d"%(n**2))
        yield i**2

调用该生成器时,没有任何代码会被立即执行:

>>> gen=squares()
>>> gen
<generator object squares at 0x7f166f7b6fc0>

直到你从该生成器中请求元素时,它才会开始执行其代码:

>>> for x in gen:
...     print(x)
... 
Generating squares from 1 to 100
1
Generating squares from 1 to 100
4
Generating squares from 1 to 100
9
Generating squares from 1 to 100
16
Generating squares from 1 to 100
25
Generating squares from 1 to 100
36
Generating squares from 1 to 100
49
Generating squares from 1 to 100
64
Generating squares from 1 to 100
81
Generating squares from 1 to 100
100

假设我们希望找出“将1美元(即100美分)兑换成任意一组硬币”的所有唯一方式。你可能会想出很多种实现方法(包括“已找到的唯一组合”的保存方式)。下面我们编写一个生成器来产生这样的硬币组合(硬币面额用整数表示):

def make_change(amount,coins=[1,5,10,25],hand=None):
    hand=[] if hand is None else hand
    if amount==0:
        yield hand
    for coin in coins:
        # 确保我们给出的硬币没有超过总额,且组合是唯一的
        if coin>amount or (len(hand)>0 and hand[-1]<coin):
            continue
        for result in make_change(amount-coin,coins=coins,
                                  hand=hand+[coin]):
            yield result

这个算法的细节并不重要(你能想出更短点的办法吗?)。然后我们可以编写:

>>> for way in make_change(100,coins=[10,25,50]):
...     print (way)
... 
[10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
[25, 25, 10, 10, 10, 10, 10]
[25, 25, 25, 25]
[50, 10, 10, 10, 10, 10]
[50, 25, 25]
[50, 50]

生成器表达式

生成器表达式(generator expression)是构造生成器的最简单方式。生成器也有一个类似于列表、字典、集合推导式的东西,其创建方式为,把列表推导式两端的方括号改成圆括号:

>>> gen=(x**2 for x in range(100))
>>> gen
<generator object <genexpr> at 0x7f166f7b6f10>

它跟下面这个冗长得多的生成器是完全等价的:

def make_gen():
    for x in range(100):
        yield x**2
gen=make_gen()

生成器表达式可用于任何接受生成器的Python函数:

>>> sum(x**2 for x in range(100))
328350
>>> dict((i,i**2) for i in range(5))
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值