Die Verwendung für ... sonst in Python-Generatoren
Frage
Ich bin ein großer Fan von Python für ... else Syntax - es ist erstaunlich, wie oft es ist anwendbar, und wie effektiv es Code vereinfachen
.Allerdings habe ich nicht einen schönen Weg gefunden, es in einem Generator zu verwenden, zum Beispiel:
def iterate(i):
for value in i:
yield value
else:
print 'i is empty'
Im obigen Beispiel, würde Ich mag die print
Anweisung nur dann ausgeführt werden, wenn i
leer. Doch wie else
nur break
und return
respektiert wird immer ausgeführt, unabhängig von der Länge der i
.
Wenn es unmöglich for...else
auf diese Weise zu verwenden, was ist der beste Ansatz, um dies so, dass die print
Anweisung nur dann ausgeführt wird, wenn nichts nachgegeben wird?
Lösung
Sie brechen die Definition eines Generators, der eine StopIteration Ausnahme auslösen soll, wenn Iteration abgeschlossen ist
(die automatisch durch eine Rückrechnung in einer Generatorfunktion behandelt wird)So:
def iterate(i):
for value in i:
yield value
return
Bester der aufrufende Code behandeln den Fall eines leeren Iterator lassen:
count = 0
for value in iterate(range([])):
print value
count += 1
else:
if count == 0:
print "list was empty"
Könnte ein sauberer Weg, um die oben zu tun, aber das sollte gut funktionieren, und fällt nicht in eine der gemeinsamen ‚Behandlung einen Iterators wie eine Liste‘ Fallen unten.
Andere Tipps
Es gibt ein paar Möglichkeiten, dies zu tun. Sie können immer die Iterator
direkt verwenden:
def iterate(i):
try:
i_iter = iter(i)
next = i_iter.next()
except StopIteration:
print 'i is empty'
return
while True:
yield next
next = i_iter.next()
Aber wenn Sie mehr darüber wissen, was aus dem Argumente i
zu erwarten, können Sie mehr prägnant sein:
def iterate(i):
if i: # or if len(i) == 0
for next in i:
yield next
else:
print 'i is empty'
raise StopIteration()
einige der früheren Antworten zusammenfassend, könnte es wie folgt gelöst werden:
def iterate(i):
empty = True
for value in i:
yield value
empty = False
if empty:
print "empty"
so gibt es wirklich keine "else" Klausel beteiligt.
Wie Sie beachten, erkennt for..else
nur eine break
. So ist es nur anwendbar, wenn Sie nach etwas suchen und dann Stop .
Es ist nicht für Ihren Zweck nicht, weil es ein Generator, aber , da Sie alle Elemente verarbeiten, ohne zu stoppen (weil Sie wollen, dass sie alle erhalten, aber das ist nicht der Punkt).
So Generator oder nicht, müssen Sie wirklich ein boolean, wie in Ber-Lösung.
Wenn es unmöglich ist, zu verwenden für ... sonst auf diese Weise, was ist der beste Ansatz, um dies so, dass die Print-Anweisung nur dann ausgeführt wird, wenn nichts nachgegeben wird?
Maximale ich mir vorstellen kann:
>>> empty = True
>>> for i in [1,2]:
... empty = False
... if empty:
... print 'empty'
...
>>>
>>>
>>> empty = True
>>> for i in []:
... empty = False
... if empty:
... print 'empty'
...
empty
>>>
Was ist einfache if-else?
def iterate(i):
if len(i) == 0: print 'i is empty'
else:
for value in i:
yield value