收益率与回报的不同结果

发布于 2024-08-18 02:34:15 字数 1567 浏览 6 评论 0原文

我真的不明白 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。

我最终通过注释掉该行 < 找到了使代码工作的方法code>firstG, secondaryG = f(first), f(second) 并替换行

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

by

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

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

I don't really understand how yield statement works in this situation. The problem says that given an expression without parentheses, write a function to generate all possible fully parenthesized (FP) expressions. Say, the input is '1+2+3+4' which should be generated to 5 FP expressions:

  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)

My code is as follows.

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

If I use return statement (the commented out lines), then the code works as expected. However, when I change to yield statement as the code shows, I only get the first 4 results. If the number of operands of the input expression is increased, then of course more results will be lost. For example, for the input '1+2+3+4+5', I only get 8 instead of 14.

I finally figure out the way to make the code work by commenting out the line firstG, secondG = f(first), f(second) and replace the line

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

by

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

That means some 'information' of the generator is lost because of the line firstG, secondG = f(first), f(second) but I can't figure out the real reason. Could you guys give me some ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

月下伊人醉 2024-08-25 02:34:15

问题是您正在迭代生成器而不是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  ^^^^^^^^^

非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

The problem is you're iterating over generators instead of lists in the yield version, specifically secondG which is exhausted after one loop. Change the line to this and it works:

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

Or, you can change your loop:

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

The non-yield version works because you return lists, which can be iterated over again, unlike generators. Also note you only iterate over firstG once, so it's not affected.

Remember that this:

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

Is equivalent to:

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

Which more clearly shows the repeated loop over B.

Another example:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文