【问题标题】:Different results from yield vs return收益率与回报的不同结果
【发布时间】:2011-01-03 11:34:30
【问题描述】:

我真的不明白yield 语句在这种情况下是如何工作的。问题是给定一个没有括号的表达式,编写一个函数来生成所有可能的全括号(FP)表达式。比如说,输入是'1+2+3+4',应该生成5个FP表达式:

  1. (1+(2+(3+4)))
  2. (1+((2+3)+4))
  3. ((1+2)+(3+4))
  4. ((1+(2+3))+4)
  5. (((1+2)+3)+4)

我的代码如下。

OPS = ('+', '-', '*', '/')
def f(expr):
    """
    Generates FP exprs
    Recursive formula: f(expr1[op]expr2) = (f(expr1) [op] f(expr2))
    """
    if expr.isdigit(): yield expr
#       return [expr]

#   ret = []
    first = ''
    i = 0
    while i < len(expr):
        if expr[i] not in OPS:
            first += expr[i]
            i += 1
        else:
            op = expr[i]
            i += 1
            second = expr[i:]
            firstG, secondG = f(first), f(second)
            for e in ('(' + e1 + op + e2 + ')' for e1 in firstG for e2 in secondG):
                yield e
#               ret.append(e)
            first += op
#    return ret

如果我使用return 语句(注释掉的行),那么代码将按预期工作。但是,当我按照代码所示更改为 yield 语句时,我只得到前 4 个结果。如果输入表达式的操作数增加,那么当然会丢失更多的结果。例如,对于输入 '1+2+3+4+5',我只得到 8 而不是 14。

我终于弄清楚了通过注释掉firstG, secondG = f(first), f(second)这一行并替换该行来使代码工作的方法

for e in ('(' + e1 + op + e2 + ')' for e1 in firstG for e2 in secondG):

通过

for e in ('(' + e1 + op + e2 + ')' for e1 in f(first) for e2 in f(second)):

这意味着由于firstG, secondG = f(first), f(second) 行而丢失了生成器的一些“信息”,但我无法弄清楚真正的原因。大家能给我一些意见吗?

【问题讨论】:

  • 请编辑问题并修正程序的缩进。在 Python 程序中,错误的缩进尤其令人讨厌。
  • 对不起,这是因为我不熟悉标签代码在这里的工作方式。我已经修好了。谢谢
  • 把它标记为作业,因为我的印象是。
  • 我认为问题可能出在调用它的代码中,你能告诉我们你是如何使用它的吗?

标签: python recursion yield


【解决方案1】:

问题是您正在迭代生成器而不是 yield 版本中的列表,特别是 secondG 在一个循环后耗尽。将行更改为此,它可以工作:

firstG, secondG = f(first), list(f(second))

或者,您可以更改循环:

for e in ("(%s%s%s)" % (e1, op, e2) for e1 in f(first) for e2 in f(second)):
#                               new generator object every loop  ^^^^^^^^^

non-yield 版本有效,因为您返回列表,与生成器不同,列表可以再次迭代。另请注意,您只迭代 firstG 一次,因此不受影响。

记住这一点:

r = [v for a in A for b in B]

相当于:

r = []
for a in A:
  for b in B:
    r.append(v)

这更清楚地显示了 B 上的重复循环。

另一个例子:

def y():
  yield 1
  yield 2
  yield 3
def r():
  return [1, 2, 3]

vy = y()
for v in vy:
  print v
for v in vy:
  print v

print "---"

vr = r()
for v in vr:
  print v
for v in vr:
  print v

【讨论】:

    猜你喜欢
    • 2020-02-18
    • 2011-04-20
    • 1970-01-01
    • 1970-01-01
    • 2018-01-23
    • 2010-12-01
    • 2013-04-07
    • 1970-01-01
    • 2017-12-09
    相关资源
    最近更新 更多