【问题标题】:Generator doesn't behave as expected生成器未按预期运行
【发布时间】:2016-05-01 22:48:04
【问题描述】:

我是生成器的新手。为什么当我将 print 替换为 yield (Python 2.7)

时,带有 print 语句的第一个正确函数不起作用

首先使用 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')

然后是没有给出所有组合的生成器

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')

【问题讨论】:

  • 感谢您的回答!

标签: python function generator


【解决方案1】:

虽然print 从您所在的任何嵌套调用中打印,但生成器仅从第一级产生。如果您需要“调用生成器”以获取更多要生成的值,则必须使用内部生成器中的值并将它们生成如下:

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

警告:虽然代码现在产生更多值,但我不保证结果是正确的。编码 仅展示,如何处理内部生成器生成的值。

注意:在 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_)

【讨论】:

  • 那么在生成器中使用递归是不是一个坏主意?
  • @TomKivy 不,嵌套生成器很好,只需要正确处理(一旦得到它就没有魔法)。
【解决方案2】:

使用递归时,需要重新生成结果。

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

这在 Python 3.X 中变得更容易,您可以yield from iterables 而不必循环。

【讨论】:

    【解决方案3】:

    更改生成器函数的最后两行

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

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

    虽然您的打印函数不会返回或产生任何内容,但您可以简单地递归调用它。但是对于返回或产生的递归函数,这些值必须从递归中传回,因此返回或在这里产生。

    【讨论】:

      【解决方案4】:

      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
      

      在 python 3.3 及更高版本中,您可以使用 yield from 代替

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-05-16
        • 2016-03-28
        • 2021-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-15
        相关资源
        最近更新 更多