【问题标题】:How two consecutive yield statement work in python?python中两个连续的yield语句如何工作?
【发布时间】:2018-03-08 11:49:30
【问题描述】:

我在合并和拆分部分偶然发现了来自pymotw.com 的这段代码。

from itertools import *


def make_iterables_to_chain():
    yield [1, 2, 3]
    yield ['a', 'b', 'c']


for i in chain.from_iterable(make_iterables_to_chain()):
    print(i, end=' ')
print()

我无法理解 make_iterables_to_chain() 是如何工作的。它包含两个yield语句,它是如何工作的? 我知道生成器是如何工作的,但是那里只有一个 yield 语句。

请帮忙!

【问题讨论】:

  • 可能只有一个yield语句,但它不是在循环中吗?
  • 有两个。我只是不明白两个收益率的基本原理。我以为一旦遇到产量,它就不会转到其他产量,但事实并非如此。

标签: python python-3.x generator yield


【解决方案1】:

单个yield 的工作方式相同。

您可以在生成器中拥有任意数量的yields,当在其上调用__next__ 时,它将执行直到遇到下一个yield。然后你取回产生的表达式,生成器会暂停,直到再次调用 __next__ 方法。

在生成器上运行几个next 调用以查看:

>>> g = make_iterables_to_chain()  # get generator
>>> next(g) # start generator, go to first yield, get result
[1, 2, 3]
>>> next(g) # resume generator, go to second yield, get result
['a', 'b', 'c']
>>> # next(g) raises Exception since no more yields are found 

【讨论】:

    【解决方案2】:

    生成器有效地允许函数返回多次。每次执行yield语句,都会将值返回给调用者,调用者可以继续执行函数。

    通常,它们在for 循环中用作可迭代对象。

    以下函数将可迭代对象中的每个元素递增一个数量:

    def inc_each(nums, inc):
        for i in nums:
            yield i + inc
    

    这里是一个用法示例:

    gen = inc_each([1, 2, 3, 4], 100)
    print(list(gen)) # [101, 102, 103, 104]
    

    list 在这里用于将任意可迭代(在本例中为生成器)转换为列表。

    你描述的函数执行两个yield语句:

    def make_iterables_to_chain():
        yield [1, 2, 3]
        yield ['a', 'b', 'c']
    

    如果您调用它,它会返回一个生成器,如果迭代,生成列表[1, 2, 3]['a', 'b', 'c']

    gen = make_iterables_to_chain()
    print(list(gen)) # [[1, 2, 3], ['a', 'b', 'c']]
    

    这是一种可以实现的方式:

    def from_iterable(iterables):
        for iterable in iterables:
            for i in iterable:
                yield i
    

    【讨论】:

    • 您的意思是,当第一次调用 make_iterables_to_chain() 时,它给出了第一个 yield 语句,即 [1,2,3],而当第二次调用它时,调用了第二个 yield 语句,即 [' a', 'b', 'c']
    • @ispeedster 生成器表达式实际上有一个额外的间接层。当您调用make_iterables_to_chain 时,它会返回一个生成器对象,可以使用iter()next() 进行迭代(尽管这通常由for 循环自动处理)。所以函数本身只被调用一次,但是结果对象可以被迭代并且可以产生多个值。
    猜你喜欢
    • 2016-04-08
    • 1970-01-01
    • 1970-01-01
    • 2016-11-22
    • 2020-06-12
    • 2020-04-07
    • 1970-01-01
    • 2011-10-15
    • 1970-01-01
    相关资源
    最近更新 更多