Python 学习笔记(十二):生成器 generator

生成器

  • 一种能够动态(循环一次计算一次返回一次)提供数据的可迭代对象。在循环过程中,按照某种算法推算数据,不必创建容器存储完整的结果,从而节省内存空间。数据量越大,优势越明显。以上作用也称之为延迟操作或惰性操作,通俗的讲就是在需要的时候才计算结果,而不是一次构建出所有结果。

生成器和迭代器

  • 所有的生成器都是迭代器,因为生成器完全实现了迭代器接口;但两者也有所不同,迭代器用于从可迭代对象(如集合)中取出元素,而生成器 “凭空” 生成元素,但大多数情况下把生成器和迭代器视作同一概念。

生成器函数

  • 只要 Python 函数的定义体中有 yield 关键字,该函数就是生成器函数。调用生成器函数时,会返回一个生成器对象。也就是说,生成器函数是生成器工厂。
# 定义一个生成器函数
def gen_123():
    yield 1
    yield 2
    yield 3

# 调用 gen_123 函数会返回一个生成器对象,而不执行
g = gen_123()
print(type(g))  # <class 'generator'>
for i in g:  
    print(i, end=" ")  # 1 2 3

生成器函数执行过程

(1) 调用生成器函数会自动创建迭代器对象。
(2) 调用迭代器对象的__next__()方法时才执行生成器函数。
(3) 每次执行到yield语句时返回数据,暂时离开。
(4) 待下次调用__next__()方法时继续从离开处继续执行。

生成器创建迭代器对象的规则

– 将yield关键字以前的代码放在next方法中。
– 将yield关键字后面的数据作为next方法的返回值。

# 由于生成器完全实现了迭代器的接口,因此可以调用 next(g) 获取下一个元素
g = gen_123()
print(g.next)  # 1
print(g.next)  # 2
print(g.next)  # 3
print(g.next)  # 报错 StopIteration: 

生成器函数“返回值” 和 return 返回值

  • 与其说生成器函数的 “返回值” ,更准确的说应该是产出或生成值。调用生成器函数返回生成器,生成器产出或生成值。生成器不会以常规的方式“返回”值,或者说生成器函数每次 “返回值” 的时候都会说 “我还会回来的” ,直到函数定义体执行完毕。生成器函数定义体中的使用 return 语句会触发生成器对象抛出 StopIteration 异常。但生成器函数中的 return 不是必须的,生成器函数的定义体执行完毕后,生成器对象会抛出 StopIteration 异常从而结束程序。

另一个句法:yield from

  • 如果生成器函数需要产出另一个生成器生成的值,传统的解决方法是使
    用嵌套的 for 循环。如:
def get_item(*iterables):
    for i in iterables:
        for j in i:
            yield j

a = ['A', 'B', 'C']
b = 'efg'
g = get_item(a, b)
for item in g:
    print(item, end=" ")
>>> A B C e f g 
  • 但引入句法 yield from 可改为:
def get_item(*iterables):
    for i in iterables:
        yield from i

a = ['A', 'B', 'C']
b = 'efg'
g = get_item(a, b)
for item in g:
    print(item, end=" ")
>>> A B C e f g 

其中 yield from i 完全代替了内层的 for 循环。除了代替循环之外,yield from 还会创建通道,把内层生成器直接与外层生成器的客户端联系起来。把生成器当成协程使用时,这个通道不仅能为客户端代码生成值,还能使用客户端代码提供的值。

生成器表达式

1.定义:用推导式形式创建生成器对象。

  • 生成器表达式背后遵守了迭代器协议,可以逐个地产出元素,而不是先建立一个完整的列表,然后再把这个列表传递到某个构造函数里。这样的方式显然能够节省内存。

2.语法:生成器表达式的语法跟列表推导差不多,只不过把方括号换成圆括号而
已。

变量 = (表达式 for 变量 in 可迭代对象 [if 真值表达式])
>>> colors = ['black', 'white']
>>> sizes = ['S', 'M', 'L']
>>> for tshirt in ('%s %s' % (c, s) for c in colors for s in sizes): 
...
print(tshirt)
...
black S
black M
black L
white S
white M
white L
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值