【问题标题】:how to use python's yield statement如何使用python的yield语句
【发布时间】:2012-11-29 21:40:03
【问题描述】:

我有一个项目列表,并希望生成所有可能的子集。因此,我使用了一个递归函数,其中项目编号和所有选定项目的列表作为参数。该函数以 0 作为第一个参数调用,并执行以下操作:

  • 它查看索引参数描述的项目
  • 它选择它
  • 它使用递增的索引参数调用自身
  • 它取消选择项目
  • 它使用递增的索引参数调用自身

我需要可能的子集来优化某些内容,但由于列表会很长,我无法查看所有子集。起初我尝试使用蛮力来考虑所有子集,但这是一个幼稚的想法。现在新计划是创建一个贪心算法,它采用第一个“有用的”选择:我想查看所有子集,直到找到一个适合我需要的子集,并认为 python 的 yield 语句正是正确的选择。这是一些代码:

def bruteForceLeft(selected,index):
    #left is the list of which i need subsets
    #its a gobal variable. to test the code, just make sure that you have a 
    #list called left in scope
    if index==len(left):
        #print(selected)
        yield selected
    else:
        #the algorithm stores the selection in a tuple of two lists
        #that's necessary since there's a second list called right as well
        #I think you can just ignore this. Think of selected as a list that
        #contains the current selection, not a tuple that contains the current
        #selection on the right as well as the left side.
        selected[0].append(left[index])
        bruteForceLeft(selected,index+1)
        selected[0].pop()
        bruteForceLeft(selected,index+1)

#as you can see I pass a tuple of two empty lists to the function.
#only the first one is used in this piece of code
for option in bruteForceLeft( ([],[]) ,0):
    print(option)
    #check if the option is "good"
    #break

输出是:什么都没有

起初我以为我在生成子集时出错了,但是在 if 条件下你可以看到我有一个注释打印语句。如果我取消注释这个打印语句,而是注释掉 yield 语句,所有可能的选择都会被打印 - 并且 for 循环被破坏了

使用 yield 语句,代码运行没有错误,但它也不做任何事情。

【问题讨论】:

  • 我还是不明白这应该是什么输入/输出。
  • 这不会回答您的问题,但除非您将此作为练习,否则可能值得检查itertools.combinations。我相信所有子集都是长度(1)到长度(n)组合的并集
  • goncalopp,你刚刚提醒了我为什么我喜欢 python
  • @lhk we all do :)
  • 有史以来唯一最流行的python问题!? The Python yield keyword explained

标签: python generator yield subset


【解决方案1】:

问题是当您递归调用bruteForceLeft 时,产生的值不会神奇地从封闭函数中产生。因此,您需要自己重新生成它们:

def bruteForceLeft(selected,index):
    #left is the list of which i need subsets
    if index==len(left):
        #print(selected)
        yield selected
    else:
        #the algorithm stores the selection in a tuple of two lists
        #that's necessary since there's a second list called right as well
        #I think you can just ignore this. Think of selected as a list that
        #contains the current selection, not a tuple that contains the current
        #selection on the right as well as the left side.
        selected[0].append(left[index])
        for s in bruteForceLeft(selected,index+1):
            yield s
        selected[0].pop()
        for s in bruteForceLeft(selected,index+1):
            yield s

(编辑:我实际上只是对此进行了测试,您的代码有错误,但我很确定问题不是重新生成)

【讨论】:

  • 嗯,我可以在 6 分钟内接受答案 - 我想我们必须等待
  • 好的。您是否有一个全局变量 left 或其他什么?我真的很困惑这段代码是如何工作的。 (当我运行它时它会抛出错误)
  • 是的。 left 是一个全局变量。我以为 cmets 已经记录了这一点,但你是对的。他们只说左边是一个列表。我会编辑那个
猜你喜欢
  • 2020-04-07
  • 2020-06-21
  • 2018-03-08
  • 1970-01-01
  • 2021-07-26
  • 2010-10-19
  • 2019-03-02
  • 2016-04-08
相关资源
最近更新 更多