简体   繁体   English

生成器的行为不符合预期

[英]Generator doesn't behave as expected

I am new to generators. 我是发电机新手。 Why does the first correct function with a print statement doesn't work when I replace the print with yield (Python 2.7) 当我用yield替换打印内容时,为什么带有print语句的第一个正确函数不起作用(Python 2.7)

First the correct function with print: 首先打印正确的功能:

def make_all_pairs(list_):
    pivot = list_.pop(0)
    for el in list_:
        pair = (pivot, el)
        print pair
    if len(list_) > 1:
        make_all_pairs(list_)      

make_all_pairs(["a","b","c","d","e"])

('a', 'b')  
('a', 'c')  
('a', 'd')  
('a', 'e')  
('b', 'c')  
('b', 'd')  
('b', 'e')  
('c', 'd')  
('c', 'e')  
('d', 'e')

Then the generator which doesn't give all the combinations 然后没有给出所有组合的发电机

def make_all_pairs(list_):
    pivot = list_.pop(0)
    for el in list_:
        pair = (pivot, el)
        yield pair
    if len(list_) > 1:
        make_all_pairs(list_)

x = make_all_pairs(["a","b","c","d","e"])
for el in x:
    print el

('a', 'b')
('a', 'c')
('a', 'd')
('a', 'e')

While print prints from whatever nesting of calls you are at, generators yield only from the first level. 尽管print从您处于的呼叫嵌套中进行的,但生成器仅从第一层产生。 If you need to "call generator" to get more values to yield, you have to consume the values from the inner generator and yield them out as follows: 如果需要“调用生成器”以获取更多值以产生,则必须使用内部生成器中的值并按以下方式产生它们:

def make_all_pairs(list_):
    pivot = list_.pop(0)
    for el in list_:
        pair = (pivot, el)
        yield pair
    if len(list_) > 1:
        for itm in make_all_pairs(list_):
            yield pair

x = make_all_pairs(["a","b","c","d","e"])
for el in x:
    print el

Warning: While the code yields more values now, I do not guarantee, the result is correct. 警告:虽然代码现在产生更多的值,但我不能保证结果是正确的。 The code only shows, how to deal with values generated by inner generator. 该代码仅显示如何处理内部生成器生成的值。

Note: In python 3 you may use alternative construct yield from 注意:在python 3中,您可以使用yield from

def make_all_pairs(list_):
    pivot = list_.pop(0)
    for el in list_:
        pair = (pivot, el)
        yield pair
    if len(list_) > 1:
        yield from make_all_pairs(list_)

When using recursion, you need to re-yield the result. 使用递归时,您需要重新获得结果。

def make_all_pairs(list_):
    pivot = list_.pop(0)
    for el in list_:
        pair = (pivot, el)
        yield pair
    if len(list_) > 1:
        for pair in make_all_pairs(list_):
            yield pair

This is made easier in Python 3.X where you can yield from iterables rather than having to loop. 在Python 3.X中,这变得更容易了,您可以在其中yield from可迭代对象中获益,而不必循环。

Change the last two lines of your generator function 更改生成器函数的最后两行

if len(list_) > 1:
    make_all_pairs(list_)

to

if len(list_) > 1:
    for pair in make_all_pairs(list_):
        yield pair

While your printing function does not return or yield anything, you can simply call it recursively. 虽然您的打印功能不返回或不产生任何结果,但是您可以简单地递归调用它。 However for a recursive function that returns or yields, those values have to be passed back up out of the recursion, thus returned or, here, yielded. 但是,对于返回或屈服的递归函数,必须将这些值从递归中传递回来,从而返回或屈服。

The answer in python 2.7 isn't great: python 2.7中的答案不是很好:

def make_all_pairs(list_):
    pivot = list_.pop(0)
    for el in list_:
        pair = (pivot, el)
        yield pair
    if len(list_) > 1:
        for pair in make_all_pairs(list_):
            yield pair


x = make_all_pairs(["a","b","c","d","e"])
for el in x:
    print el

In python 3.3 and greater you can use yield from instead 在python 3.3及更高版本中,您可以改用yield from

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM