关于Python Generators的常见误解

作者: Jeff Knupp

原文链接:https://jeffknupp.com/blog/2018/06/04/a-common-misunderstanding-about-

python-generators/

几天前,我收到了下面的信:

Jeff

看起来你知道迭代器。也许你可以解释某个奇怪的行为。如果你运行下面的代码,你会发现该函数处理得不一样,因为它在某处有一个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关键字的函数自动被转换为一个generator。它返回的是一个generator迭代器。我们的打印输出实际上暗示了这一点:

$ python yield.py <generator object func at 0x10e968a50>

在执行x = func()时,我们实际上没有执行func()里的任何代码。相反,因为func()是一个generator,返回了一个generator迭代器。因此,虽然这可能看起来像一个函数调用,它实际上给予我们用来生成该generator产生值的generator迭代器。

因此,我们实际上应该如何“调用”一个generator呢?通过在一个generator迭代器上调用next()。在上面的代码中,将对由func()返回的generator迭代器执行next调用,并绑定到x

如果我们希望看到那个神秘的消息被打印出来,只要把最后一行代码改为print(next(x))

当然,一遍一遍地调用next()意味着作为一个迭代器处理是有点麻烦。幸运地,for循环支持在generator迭代器上的迭代。设想如下的一个玩具generator实现:

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来实际执行这个generator里的代码。

总结

我希望这能澄清关于Pythonyieldgenerators的某些常见问题。这个话题更深入的教程,参考Improve Your Python: 'yield' and Generators Explained

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值