2010-01-10 13 views
5

Ich verstehe nicht wirklich, wie yield Anweisung in dieser Situation funktioniert. Das Problem besagt, dass bei einem Ausdruck ohne Klammern eine Funktion zum Generieren aller möglichen vollständig geklammerten (FP) Ausdrücke geschrieben wird. Sprich, der Eingang, der 5 '1+2+3+4' FP Ausdrücke erzeugt werden soll:Unterschiedliche Ergebnisse von Rendite und Rendite

  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)

Mein Code ist wie folgt.

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 

Wenn ich return Aussage (die auf Kommentar Zeilen) verwenden, dann funktioniert der Code wie erwartet. Wenn ich jedoch zu yield Statement wechsle, wie der Code zeigt, bekomme ich nur die ersten 4 Ergebnisse. Wenn die Anzahl der Operanden des Eingabeausdrucks erhöht wird, gehen natürlich mehr Ergebnisse verloren. Zum Beispiel für die Eingabe '1+2+3+4+5', bekomme ich nur 8 statt 14

ich endlich den Weg finden, um den Code Arbeit zu machen, indem die Linie firstG, secondG = f(first), f(second) kommentieren und ersetzen Sie die Zeile

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

von

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

, dass einige ‚Informationen‘ des Generators Mittel wegen der Linie verloren firstG, secondG = f(first), f(second) aber Ich kann den wahren Grund nicht herausfinden. Könnt ihr mir ein paar Ideen geben?

+0

Bitte geben Sie die Frage bearbeiten und die Vertiefung des Programms beheben.In Python-Programmen ist das falsche Einrücken besonders ärgerlich. – avakar

+0

Es tut mir leid, weil ich nicht weiß, wie der Tag-Code hier funktioniert. Ich habe es bereits behoben. Danke – user247468

+0

hat es als Hausaufgabe getaggt, da ich den Eindruck hatte, dass es ist. –

Antwort

4

Das Problem ist, dass Sie über Generatoren statt Listen in der Yield-Version, speziell secondG Iterieren, die nach einer Schleife erschöpft ist. Ändern Sie die Zeile auf diese und es funktioniert:

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

Oder können Sie Ihre Schleife ändern:

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

Die nicht-Yield-Version funktioniert, weil Sie eine Liste zurückkehren, was wiederum iteriert werden kann, im Gegensatz zu Generatoren. Beachten Sie auch, dass Sie nur über firstG einmal iterieren, so dass es nicht betroffen ist.

Denken Sie daran, dass dies:

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

entspricht:

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

Welche deutlicher die wiederholte Schleife über B zeigt.

Ein weiteres Beispiel:

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 
+0

Gotcha;) Danke, Roger! – user247468

Verwandte Themen