老男孩教育专注IT教育10余年,只培养IT技术精英

全国免费咨询电话(渠道合作):400-609-2893

Python课程中什么是生成器?生成器如何使用?

老男孩IT教育

常见问题

2021年8月23日 18:27

生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面一样在类中定义__iter__() 和__next__() 方法了,只需要在函数中声明一个 yiled 关键字。 所以生成器是一种特殊的迭代器(反之不成立),因此任何生成器也是以一种懒加载的模式生成值。

  生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面一样在类中定义__iter__() 和__next__() 方法了,只需要在函数中声明一个 yiled 关键字。 所以生成器是一种特殊的迭代器(反之不成立),因此任何生成器也是以一种懒加载的模式生成值。用生成器来实现斐波那契数列的例子是:

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1

for i in fib(10):
    print(i)

  (1)生成器对象

  简单说,生成器就是使用了yield关键字的函数:

def countdown(n):
    print('countdown start')
    while n > 0:
        yield n
        n -= 1
    print('Done!')


print(countdown)  # <function countdown at 0x000001CDD6A2F040>
gen = countdown(5)
print(gen)  # <generator object countdown at 0x000001CDD6B82350>

# 生成器对象也是迭代器对象,一定拥有iter和next,由yield关键字在函数调用时封装好的,不用再自己定义
# print(gen.__iter__())
# print(gen.__next__())
# print(gen.__next__())
# print(gen.__next__())

for i in gen:
    print(i)

  解析:生成器函数调用时只会返回一个生成器对象。只有当生成器对象调用__next__方法时才会触发函数体代码执行,直到遇到关键字yield停止,将yield后的值作为返回值返回,所以,yield类似于return的功能,但不同于return的是,return返回,函数结束;而yield将函数的状态挂起,等待生成器对象再次调用__next__方法时,函数从挂起的位置后的第一条语句继续运行直到再遇见yield并返回其后的值;如果不断调用__next__方法,最后一次进入函数体,待执行代码不再有yield此时报出迭代异常的错误。

  另外,对比迭代器,生成器对象多几个方法:

  (1)一个内置的close方法用来关闭自己

  (2)一个内置的send方法,进入生成器,类似于next,但是多一个传值给yield变量的功能。

  yield的功能总结:

  (1)封装iter和next方法 (2)执行函数时遇到yield返回其后的值,不同于return,yiled可以返回多次值 (3)挂起函数的状态,等待下一次调用next方法时找到对应的暂停位置继续执行。

  生成器表达式

  创建一个生成器对象有两种方式,一是通过在函数中创建yield关键字来实现。另一种就是生成器表达式,这是一种类似于数据类型中学过的列表生成式的语法格式,只是将[]换成(),即:

(expression for item in iterable if condition)

  不同于列表生成式最后返回一个列表结果,生成器表达式顾名思义会返回一个生成器对象,比如:

>>> [x*x for x in range(4)]  # 列表推导式
[0, 1, 4, 9]
>>> gen=(x*x for x in range(4))
>>> gen
<generator object <genexpr> at 0x101be0ba0>

  当需要用到其中的值时,再通过调用next方法或者for循环将值一个个地计算出来:

>>> next(gen)
0
>>> next(gen)
1
>>> next(gen)
4
>>> next(gen)
9
>>> next(gen)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

#------------for 循环------------------
>>> gen=(x*x for x in range(4))
>>> for i in gen:
...     print(i)
...
0
1
4
9

  可迭代对象、迭代器、生成器关系

Python培训班

  面试题

def add(s, x):
    return s + x

def gen():
    for i in range(4):
        yield i

base = gen()
for n in [1, 10]:
    base = (add(i, n) for i in base)

print(list(base))

  想要学习Python,却又担心找不到合适的培训机构,在这里推荐大家来老男孩教育,我校Python课程免费试听。

  推荐阅读:

  【学习必看】Python面试宝典之Python基础

  Python中好用的编程神器!老男孩Python培训班

  应届生参加Python培训需要学多久?老男孩Python学习周期

本文经授权发布,不代表老男孩教育立场。如若转载请联系原作者。