python 迭代器生成器
我几天前收到以下电子邮件:
杰夫
看来您了解迭代器。 也许您可以解释一些奇怪的行为。 如果您运行下面的代码,您会发现该函数被不同地对待,因为它完全无法访问,只是因为它在某处具有“ yield”。
def func():
print("> Why doesn't this line print?")
exit() # Within this function, nothing should matter after this point. The program should exit
yield "> The exit line above will exit ONLY if you comment out this line."
x = func()
print(x)
运行代码时,我从print()
调用中获得以下输出: <generator object func at 0x10e968a50>
。
那么这是怎么回事? 为什么func()
那一行不打印? 即使yield
完全无法达到,它似乎也会影响函数的执行方式。
yield
如何影响功能
为了阐明为什么会发生这种行为,让我们回顾一下yield
。 任何包含yield
关键字的函数都会自动转换为生成器 。 它返回的内容( 生成器 )是生成器迭代器 。 我们的打印输出实际上暗示了这一点:
$ python yield.py
<generator object func at 0x10e968a50>
当执行x = func()
, 我们实际上并没有执行 func()
任何代码 。 而是,由于func()
是一个generator ,所以将返回一个generator迭代器 。 因此,尽管这看起来像是一个函数调用,但实际上是给了我们生成器迭代器,我们将用它来生成由generator产生的值。
那么,我们实际上如何“调用” 发电机 ? 通过 在生成器迭代器上 调用 next()
。 在上面的代码中,这将对func()
返回并绑定到x
的生成器迭代器执行“ next”调用。
如果我们希望看到实际打印出的隐秘消息,只需将代码的最后一行更改为print(next(x))
。
当然,一遍又一遍地调用要被视为迭代器的内容的next()
有点麻烦。 幸运的是, for
循环支持在生成器迭代器上进行迭代 。 想象一下一个玩具生成器,其实现方式如下:
def one_to_ten():
"""Return the integers between one and ten, inclusive."""
value = 1
while value <= 10:
yield value value += 1
我们可以通过以下方式在for循环中调用此方法:
for element in one_to_ten():
print(element)
当然,我们可以更详细地写:
iterator = one_to_ten()
for element in iterator:
print(element)
这类似于原始代码所做的。 它只是从未使用过x
来实际执行生成器中的代码。
摘要
我希望这能解决有关Python中 yield
和generators
一些常见问题。 有关该主题的更深入的教程,请查看“ 改进Python:'yield'和Generators Explained” 。
发表于六月04,2018由Jeff Knupp
最初于 2018 年6月4日 发布在 jeffknupp.com 上。
翻译自: https://hackernoon.com/a-common-misunderstanding-about-python-generators-dbc622914d33
python 迭代器生成器