Is er een gemakkelijkere manier om uit geneste lussen te breken dan een uitzondering te maken? (In Perl kun je elke lus een label geven en op zijn minst een buitenste lus voortzetten.)
for x in range(10):
for y in range(10):
print x*y
if x*y > 50:
"break both loops"
I.e. is er een leukere manier dan:
class BreakIt(Exception): pass
try:
for x in range(10):
for y in range(10):
print x*y
if x*y > 50:
raise BreakIt
except BreakIt:
pass
Antwoord 1, autoriteit 100%
Het is in ieder geval gesuggereerd, maar ook verworpen. Ik denk niet dat er een andere manier is, behalve het herhalen van de test of het reorganiseren van de code. Het is soms een beetje vervelend.
In het afwijzingsberichtzegt de heer van Rossum noemt het gebruik van return
, wat erg verstandig is en iets dat ik persoonlijk moet onthouden. 🙂
Antwoord 2, autoriteit 96%
for x in xrange(10):
for y in xrange(10):
print x*y
if x*y > 50:
break
else:
continue # only executed if the inner loop did NOT break
break # only executed if the inner loop DID break
Hetzelfde werkt voor diepere loops:
for x in xrange(10):
for y in xrange(10):
for z in xrange(10):
print x,y,z
if x*y*z == 30:
break
else:
continue
break
else:
continue
break
Antwoord 3, autoriteit 44%
Als je de luscode in een functie kunt extraheren, kan een return
-instructie worden gebruikt om de buitenste lus op elk moment te verlaten.
def foo():
for x in range(10):
for y in range(10):
print(x*y)
if x*y > 50:
return
foo()
Als het moeilijk is om die functie te extraheren, kun je een innerlijke functie gebruiken, zoals @bjd2385 suggereert, bijvoorbeeld
def your_outer_func():
...
def inner_func():
for x in range(10):
for y in range(10):
print(x*y)
if x*y > 50:
return
inner_func()
...
Antwoord 4, autoriteit 29%
Gebruik itertools.product!
from itertools import product
for x, y in product(range(10), range(10)):
#do whatever you want
break
Hier is een link naar itertools.product in de Python-documentatie:
http://docs.python.org/library/itertools.html#itertools.product
Je kunt ook een array-begrip herhalen met 2 fors erin, en breken wanneer je maar wilt.
>>> [(x, y) for y in ['y1', 'y2'] for x in ['x1', 'x2']]
[
('x1', 'y1'), ('x2', 'y1'),
('x1', 'y2'), ('x2', 'y2')
]
Antwoord 5, autoriteit 24%
Soms gebruik ik een booleaanse variabele. Naïef, als je wilt, maar ik vind het heel flexibel en prettig om te lezen. Het testen van een variabele kan voorkomen dat complexe omstandigheden opnieuw worden getest en kan ook resultaten van verschillende tests in binnenlussen verzamelen.
x_loop_must_break = False
for x in range(10):
for y in range(10):
print x*y
if x*y > 50:
x_loop_must_break = True
break
if x_loop_must_break: break
Antwoord 6, autoriteit 12%
Als u een uitzondering wilt maken, kunt u een StopIteration-uitzondering opwerpen . Dat zal in ieder geval de bedoeling duidelijk maken.
Antwoord 7, autoriteit 4%
Je kunt je code ook refactoren om een generator te gebruiken. Maar dit is misschien niet een oplossing voor alle soorten geneste lussen.
Antwoord 8, autoriteit 2%
In dit specifieke geval kun je de lussen samenvoegen met een moderne python (3.0 en waarschijnlijk ook 2.6) door itertools.product te gebruiken.
Voor mezelf nam ik dit als vuistregel: als je te veel lussen nest (zoals in, meer dan 2), kun je meestal een van de lussen extraheren in een andere methode of de lussen samenvoegen tot één, zoals in dit geval.