5

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'14 ではなく 8 しか得られません。

行をコメントアウトして行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

1 に答える 1

4

問題は、yieldバージョンのリストではなく、ジェネレーター、具体的には1つのループの後に使い果たされる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  ^^^^^^^^^

非イールドバージョンは、ジェネレーターとは異なり、リストを返すために機能します。リストは繰り返し繰り返すことができます。また、firstGを1回だけ繰り返すため、影響を受けないことに注意してください。

これを覚えておいてください:

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
于 2010-01-10T15:05:45.460 に答える