Biorąc pod uwagę następujący kod (który nie działa):
while True:
#snip: print out current state
while True:
ok = get_input("Is this ok? (y/n)")
if ok.lower() == "y": break 2 #this doesn't work :(
if ok.lower() == "n": break
#do more processing with menus and stuff
Czy istnieje sposób, aby to zadziałało? Czy też muszę wykonać jedną kontrolę, aby wyjść z pętli wejściowej, a następnie inną, bardziej ograniczoną, sprawdzić w pętli zewnętrznej, aby zerwać wszystko razem, jeśli użytkownik jest zadowolony?
python
nested-loops
break
control-flow
Matthew Scharley
źródło
źródło
goto
jeśli jesteś głęboko osadzony w wielu pętlachOdpowiedzi:
Moim pierwszym instynktem byłoby przekształcenie zagnieżdżonej pętli w funkcję i użycie jej
return
do wybicia.źródło
return
jest właściwym podejściem. Powodem jest to, że według Zen Pythona „mieszkanie jest lepsze niż zagnieżdżone”. Mamy tutaj trzy poziomy zagnieżdżania i jeśli to zacznie przeszkadzać, nadszedł czas, aby zmniejszyć zagnieżdżenie lub przynajmniej wyodrębnić całe zagnieżdżenie do własnej funkcji.Oto inne podejście, które jest krótkie. Wadą jest to, że możesz przełamać tylko zewnętrzną pętlę, ale czasami jest to dokładnie to, czego chcesz.
Wykorzystuje konstrukcję for / else wyjaśnioną na stronie: Dlaczego Python używa pętli „else” po pętli for i while?
Kluczowy wgląd: Wydaje się , że zewnętrzna pętla zawsze pęka.Ale jeśli pętla wewnętrzna nie pęknie, pętla zewnętrzna też nie.
continue
Stwierdzenie jest magia tutaj. Jest w klauzuli for-else. Z definicji dzieje się tak, jeśli nie ma wewnętrznej przerwy. W tej sytuacjicontinue
starannie omija zewnętrzną przerwę.źródło
PEP 3136 proponuje oznaczenie przerwa / kontynuacja. Guido odrzucił go, ponieważ „tak skomplikowany kod wymagający tej funkcji jest bardzo rzadki”. PEP wspomina jednak o niektórych obejściach (takich jak technika wyjątków), podczas gdy Guido uważa, że refaktoryzacja użycia return będzie w większości przypadków prostsza.
źródło
return
jest zwykle droga, widziałem całkiem sporo przypadków, w których proste zwięzłebreak 2
stwierdzenie miałoby taki sens. Ponadto refactor /return
nie działa tak samo dlacontinue
. W takich przypadkach numeryczne dzielenie i kontynuowanie byłoby łatwiejsze do naśladowania i mniej zaśmiecone niż refaktoryzacja do małej funkcji, zgłaszanie wyjątków lub zawiłej logiki polegającej na ustawianiu flagi do rozbicia na każdym poziomie gniazda. Szkoda, że Guido go odrzucił.break; break
byłoby miło.break
wszystkie pętle. Głupi.Po pierwsze, pomocna jest zwykła logika.
Jeśli z jakiegoś powodu warunki zakończenia nie mogą zostać wypracowane, wyjątki stanowią plan awaryjny.
W tym konkretnym przykładzie wyjątek może nie być konieczny.
Z drugiej strony często mamy opcje „Y”, „N” i „Q” w aplikacjach w trybie znakowym. W przypadku opcji „Q” chcemy natychmiastowego wyjścia. To bardziej wyjątkowe.
źródło
done
). (2) zgłaszanie wyjątku. Połączenie ich w jedno rozwiązanie sprawia, że wydaje się to skomplikowane. Dla przyszłych czytelników: UŻYWAJ wszystkich wierszy obejmującychdone
LUB zdefiniujGetOutOfLoop(Exception)
i podbij / z wyjątkiem tego.raise Exception('GetOutOfLoop')
iexcept Exception:
.Zwykle zgadzam się, że refaktoryzacja do funkcji jest zwykle najlepszym podejściem w tego rodzaju sytuacjach, ale gdy naprawdę potrzebujesz wyrwać się z zagnieżdżonych pętli, oto ciekawy wariant podejścia do zgłaszania wyjątków opisanego przez @ S.Lott. Korzysta z
with
instrukcji Pythona, aby wyjątek wyglądał nieco ładniej. Zdefiniuj nowego menedżera kontekstu (musisz to zrobić tylko raz) za pomocą:Teraz możesz użyć tego menedżera kontekstu w następujący sposób:
Zalety: (1) jest nieco czystszy (brak wyraźnego bloku try-oprócz), oraz (2) otrzymujesz niestandardową
Exception
podklasę dla każdego zastosowanianested_break
; nie trzeba zaException
każdym razem deklarować własnej podklasy.źródło
Po pierwsze, możesz również rozważyć uczynienie procesu pobierania i sprawdzania poprawności danych wejściowych funkcją; w ramach tej funkcji, można po prostu zwrócić wartość, jeżeli jego poprawne, i się obracać w czasie pętli czy nie. To zasadniczo eliminuje rozwiązany problem i zwykle można go zastosować w bardziej ogólnym przypadku (zerwanie wielu pętli). Jeśli absolutnie musisz zachować tę strukturę w swoim kodzie i naprawdę nie chcesz zajmować się rachunkami logicznymi ...
Możesz także użyć goto w następujący sposób (używając modułu April Fools stąd ):
Wiem, wiem, „nie będziesz używać goto” i tak dalej, ale działa to dobrze w takich dziwnych przypadkach.
źródło
Wprowadź nową zmienną, której będziesz używać jako „przerywacza pętli”. Najpierw przypisz coś do niego (False, 0 itd.), A następnie w zewnętrznej pętli, zanim się od niego oderwiesz, zmień wartość na coś innego (True, 1, ...). Po wyjściu z pętli sprawdź w pętli „macierzystej” tę wartość. Pokażę:
Jeśli masz nieskończoną pętlę, jest to jedyne wyjście; dla innych pętli wykonywanie jest naprawdę dużo szybsze. Działa to również, jeśli masz wiele zagnieżdżonych pętli. Możesz wyjść ze wszystkich lub tylko kilku. Niekończące się możliwości! Mam nadzieję, że to pomogło!
źródło
Aby wyrwać się z wielu zagnieżdżonych pętli, bez refaktoryzacji do funkcji, skorzystaj z „symulowanej instrukcji goto” z wbudowanym wyjątkiem StopIteration :
Zobacz tę dyskusję na temat używania instrukcji goto do przełamywania zagnieżdżonych pętli.
źródło
czy jakoś tak. Możesz ustawić zmienną w wewnętrznej pętli i sprawdzić ją w zewnętrznej pętli natychmiast po wyjściu z wewnętrznej pętli, przerywając w razie potrzeby. Podoba mi się metoda GOTO, pod warunkiem, że nie masz nic przeciwko użyciu modułu żartów prima aprilis - nie jest to Python, ale ma sens.
źródło
To nie jest najładniejszy sposób na zrobienie tego, ale moim zdaniem jest to najlepszy sposób.
Jestem prawie pewien, że mógłbyś tutaj również opracować coś za pomocą rekurencji, ale nie wiem, czy to dla ciebie dobra opcja.
źródło
A dlaczego nie kontynuować pętli, jeśli dwa warunki są spełnione? Myślę, że jest to bardziej pythonowy sposób:
Czyż nie
Wszystkiego najlepszego.
źródło
while dejaVu:
? Zresztą ustawiłeś to na prawdę.True
warunkach, aby pominąć dwie pętle, ale wystarczy jedna.if not dejaVu: break
u dołu” i wyjść z głównej pętli? Myślę, że rozwiązanie jest najbliższe pytaniu. +1Uwzględnij logikę pętli w iteratorze, który zwraca zmienne pętli i zwraca po zakończeniu - oto prosty układ, który układa obrazy w wierszach / kolumnach, dopóki nie zabraknie obrazów lub miejsc, aby je umieścić:
Ma to tę zaletę, że dzieli skomplikowaną logikę pętli i przetwarzanie ...
źródło
W tym przypadku, jak zauważyli również inni, właściwym rozwiązaniem jest rozkład funkcjonalny. Kod w Pythonie 3:
źródło
W
while ... else
strukturze Pythona istnieje ukryta sztuczka , której można użyć do symulacji podwójnego podziału bez większych zmian / dodatków kodu. Zasadniczo, jeśliwhile
warunek jest fałszywy,else
blok jest wyzwalany. Ani wyjątki,continue
anibreak
wyzwalanieelse
bloku. Aby uzyskać więcej informacji, zobacz odpowiedzi na „ Else klauzula dotycząca instrukcji Python while ” lub dokumentacja Python podczas korzystania (v2.7) .Jedynym minusem jest to, że musisz przenieść warunek podwójnego łamania do
while
warunku (lub dodać zmienną flagową). Istnieją tego warianty dlafor
pętli, w którejelse
blok jest wyzwalany po zakończeniu pętli.źródło
How to break out of multiple loops in Python?
i odpowiedź powinna brzmieć: „To nie działa, spróbuj czegoś innego”. Wiem, że to naprawia dokładnie podany przykład PO, ale nie odpowiada na ich pytanie.Innym sposobem zredukowania iteracji do pętli jednopoziomowej byłoby użycie generatorów, jak również określono w odwołaniu do pytona
Możesz skalować go do dowolnej liczby poziomów dla pętli
Minusem jest to, że nie można już przekroczyć tylko jednego poziomu. To wszystko albo nic.
Kolejną wadą jest to, że nie działa z pętlą while. Pierwotnie chciałem opublikować tę odpowiedź na Pythonie - `wyrwij się ze wszystkich pętli, ale niestety jest to zamknięte jako duplikat tego
źródło
Powodem mojego przyjazdu jest to, że miałem zewnętrzną i wewnętrzną pętlę:
Jak widać, tak naprawdę nie przejdzie do następnego x, ale zamiast tego przejdzie do następnego y.
znalazłem rozwiązanie tego po prostu dwa razy przez tablicę:
Wiem, że był to konkretny przypadek pytania OP, ale piszę je w nadziei, że pomoże to komuś inaczej myśleć o ich problemie, jednocześnie zachowując prostotę.
źródło
break
zamiastcontinue
zrobiłoby to, co chcesz, prawda? :-)Spróbuj użyć nieskończonego generatora.
źródło
Korzystając z funkcji:
Spróbuj uruchomić powyższe kody, komentując
return
również.Bez użycia żadnej funkcji:
Teraz uruchom powyższe kody w pierwszej kolejności, a następnie spróbuj uruchomić, komentując każdą linię zawierającą
break
jeden na raz od dołu.źródło
Łatwym sposobem na przekształcenie wielu pętli w jedną, łamliwą pętlę jest użycie
numpy.ndindex
Musisz indeksować do swoich obiektów, w przeciwieństwie do możliwości jawnego iterowania wartości, ale przynajmniej w prostych przypadkach wydaje się to około 2-20 razy prostsze niż większość sugerowanych odpowiedzi.
źródło
źródło
prawdopodobnie mała sztuczka, jak poniżej, zrobi, jeśli nie woli refaktoryzacji do funkcji
dodano 1 zmienną break_level, aby kontrolować warunek pętli while
źródło
Możesz zdefiniować zmienną (na przykład break_statement ), a następnie zmienić ją na inną wartość, gdy wystąpi warunek dwóch przerw, i użyć jej w instrukcji if, aby również przerwać z drugiej pętli.
źródło
Chciałbym przypomnieć, że funkcje w języku Python można tworzyć bezpośrednio w środku kodu i mogą one w przejrzysty sposób uzyskać dostęp do otaczających zmiennych w celu odczytu
nonlocal
lubglobal
deklaracji do pisania.Możesz więc użyć funkcji jako „łamliwej struktury kontroli”, określającej miejsce, do którego chcesz wrócić:
źródło
Rozwiązania na 2 sposoby
Na przykład: czy te dwie macierze są równe / takie same?
macierz 1 i macierz 2 mają ten sam rozmiar, n, 2 macierze wymiarowe.
Pierwsze rozwiązanie , bez funkcji
Drugie rozwiązanie , z funkcją
Jest to ostateczne rozwiązanie dla mojej sprawy
Miłego dnia!
źródło
źródło
Mam nadzieję, że to pomaga:
źródło
Oto implementacja, która wydaje się działać:
Jedyną wadą jest to, że musisz zdefiniować
break_
przed pętlami.źródło
Podziękowania należą się Vivek Nagarajan, programista od 1987 roku
Korzystanie z funkcji
Za pomocą flagi
źródło
Podobnie jak poprzednio, ale bardziej kompaktowy. (Booleany to tylko liczby)
źródło
Ponieważ pytanie to stało się standardowym pytaniem o włamanie do określonej pętli, chciałbym udzielić odpowiedzi na przykład, używając
Exception
.Mimo że w konstrukcji wielokrotnie zapętlonej nie ma etykiety o nazwie zerwanie pętli, możemy skorzystać z wyjątków zdefiniowanych przez użytkownika, aby włamać się do wybranej przez nas pętli. Rozważ następujący przykład, w którym wydrukujmy wszystkie liczby do 4 cyfr w systemie numeracji base-6:
Kiedy wypisujemy dane wyjściowe, nigdy nie otrzymamy żadnej wartości, której jednostką jest 4. W takim przypadku nie przerywamy żadnej pętli, ponieważ
BreakLoop(4)
jest ona podnoszona i przechwytywana w tej samej pętli. Podobnie, ilekroć dziesięć miejsc ma 3, włamy się do trzeciej pętli za pomocąBreakLoop(3)
. Ilekroć sto miejsc ma 5,BreakLoop(2)
włamy się do drugiej pętli, a gdy tysiąc miejsc ma 2, włamujemy się do pierwszej pętli, używającBreakLoop(1)
.Krótko mówiąc, podnieś swój wyjątek (wbudowany lub zdefiniowany przez użytkownika) w wewnętrznych pętlach i złap go w pętli, z której chcesz wznowić kontrolę. Jeśli chcesz zerwać ze wszystkich pętli, złap wyjątek poza wszystkimi pętlami. (Nie pokazałem tego przypadku w przykładzie).
źródło