use*_*468 5 python recursion yield
我真的不明白yield声明在这种情况下是如何运作的.问题是,给定一个没有括号的表达式,编写一个函数来生成所有可能的完全括号(FP)表达式.比如,输入'1+2+3+4'应该生成5个FP表达式:
我的代码如下.
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
Run Code Online (Sandbox Code Playgroud)
如果我使用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)而丢失,但我无法弄清楚真正的原因.你们能给我一些想法吗?
小智 4
问题是你正在迭代生成器而不是yield版本中的列表,特别是在一个循环后耗尽的第二个G。将行更改为此:
firstG, secondG = f(first), list(f(second))
Run Code Online (Sandbox Code Playgroud)
或者,您可以更改循环:
for e in ("(%s%s%s)" % (e1, op, e2) for e1 in f(first) for e2 in f(second)):
# new generator object every loop ^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
非yield版本之所以有效,是因为您返回列表,与生成器不同,列表可以再次迭代。另请注意,您仅迭代firstG一次,因此它不受影响。
请记住:
r = [v for a in A for b in B]
Run Code Online (Sandbox Code Playgroud)
相当于:
r = []
for a in A:
for b in B:
r.append(v)
Run Code Online (Sandbox Code Playgroud)
这更清楚地显示了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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1194 次 |
| 最近记录: |