Diberikan kode berikut (itu tidak berfungsi):
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
Apakah ada cara untuk membuat ini berfungsi? Atau apakah saya harus melakukan satu pemeriksaan untuk keluar dari loop input, lalu yang lain, lebih terbatas, periksa di loop luar untuk memecahkan semua bersama-sama jika pengguna puas?
python
nested-loops
break
control-flow
Matthew Scharley
sumber
sumber
goto
jika Anda berada jauh di banyak loopJawaban:
Insting pertama saya adalah untuk memperbaiki loop bersarang menjadi fungsi dan digunakan
return
untuk keluar.sumber
return
adalah pendekatan yang tepat. Dan alasannya adalah bahwa, menurut Zen Python , "flat lebih baik daripada bersarang". Kami memiliki tiga tingkat sarang di sini dan jika itu mulai menghalangi, saatnya untuk mengurangi sarang atau setidaknya mengekstrak seluruh sarang ke dalam fungsinya sendiri.Ini pendekatan lain yang pendek. Kerugiannya adalah Anda hanya dapat mematahkan loop luar, tetapi kadang-kadang itulah yang Anda inginkan.
Ini menggunakan for / else construct yang dijelaskan di: Mengapa python menggunakan 'else' after for dan while loop?
Wawasan utama: Sepertinya lingkaran luar selalu putus. Tetapi jika loop dalam tidak putus, loop luar tidak akan baik.
The
continue
pernyataan adalah keajaiban di sini. Ada dalam klausa untuk yang lain. Menurut definisi itu terjadi jika tidak ada istirahat batin. Dalam situasi itucontinue
dengan rapi mengeliminasi istirahat luar.sumber
PEP 3136 mengusulkan pelabelan / lanjutkan. Guido menolaknya karena "kode sangat rumit untuk memerlukan fitur ini sangat jarang". PEP memang menyebutkan beberapa solusi, (seperti teknik pengecualian), sementara Guido merasa refactoring untuk menggunakan pengembalian akan lebih sederhana dalam banyak kasus.
sumber
return
biasanya cara untuk pergi, saya telah melihat beberapa kasus di mana pernyataan ringkas 'break 2
' hanya akan sangat masuk akal. Juga, refactor /return
tidak berfungsi sama untukcontinue
. Dalam kasus ini, numeric break dan continue akan lebih mudah diikuti dan lebih sedikit berantakan daripada refactoring ke fungsi kecil, meningkatkan pengecualian, atau logika berbelit-belit yang melibatkan pengaturan bendera untuk dipecah pada setiap level sarang. Sayang sekali Guido menolaknya.break; break
akan menyenangkan.break
semua loop. Bodoh.Pertama, logika biasa sangat membantu.
Jika, karena alasan tertentu, kondisi terminasi tidak dapat dikerjakan, pengecualian adalah rencana mundur.
Untuk contoh khusus ini, pengecualian mungkin tidak diperlukan.
Di sisi lain, kita sering memiliki opsi "Y", "N" dan "Q" dalam aplikasi mode-karakter. Untuk opsi "Q", kami ingin segera keluar. Itu lebih luar biasa.
sumber
done
). (2) mengajukan pengecualian. Menggabungkan mereka menjadi satu solusi hanya membuatnya terlihat rumit. Untuk pembaca masa depan: BAIK menggunakan semua baris yang terlibatdone
, ATAU menentukanGetOutOfLoop(Exception)
dan meningkatkan / kecuali itu.Exception
konstruktor (misalnyaraise Exception('bla bla bla')
) valid dalam Python 2 dan Python 3. Yang pertama lebih disukai dalam kasus ini karena kami tidak inginexcept
blok kami untuk menangkap semua pengecualian, tetapi hanya pengecualian khusus yang kami gunakan untuk keluar dari loop. Jika kami melakukan hal-hal seperti yang Anda sarankan, dan kemudian bug dalam kode kami menyebabkan pengecualian yang tidak terduga muncul, itu akan diperlakukan dengan salah sama seperti sengaja keluar dari loop.Saya cenderung setuju bahwa refactoring ke fungsi biasanya merupakan pendekatan terbaik untuk situasi semacam ini, tetapi untuk ketika Anda benar - benar perlu keluar dari loop bersarang, inilah varian menarik dari pendekatan peningkatan pengecualian yang dijelaskan oleh @ S.Lott. Ini menggunakan
with
pernyataan Python untuk membuat kenaikan pengecualian terlihat sedikit lebih baik. Tetapkan manajer konteks baru (Anda hanya perlu melakukan ini satu kali) dengan:Sekarang Anda dapat menggunakan manajer konteks ini sebagai berikut:
Keuntungan: (1) ini sedikit lebih bersih (tidak ada blok coba-kecuali eksplisit), dan (2) Anda mendapatkan
Exception
subkelas yang dibuat khusus untuk setiap penggunaannested_break
; tidak perlu mendeklarasikanException
subclass Anda sendiri setiap kali.sumber
Pertama, Anda juga dapat mempertimbangkan untuk membuat proses mendapatkan dan memvalidasi fungsi input; dalam fungsi itu, Anda bisa mengembalikan nilai jika itu benar, dan terus berputar di loop sementara jika tidak. Ini pada dasarnya meniadakan masalah yang Anda selesaikan, dan biasanya dapat diterapkan dalam kasus yang lebih umum (keluar dari banyak loop). Jika Anda benar-benar harus menjaga struktur ini dalam kode Anda, dan benar-benar tidak ingin berurusan dengan para boolean pembukuan ...
Anda juga dapat menggunakan goto dengan cara berikut (menggunakan modul April Mop dari sini ):
Saya tahu, saya tahu, "kamu tidak boleh menggunakan goto" dan semua itu, tetapi itu bekerja dengan baik dalam kasus-kasus aneh seperti ini.
sumber
Perkenalkan variabel baru yang akan Anda gunakan sebagai 'loop breaker'. Pertama tetapkan sesuatu untuk itu (Salah, 0, dll.), Dan kemudian, di dalam lingkaran luar, sebelum Anda memutuskannya, ubah nilainya menjadi sesuatu yang lain (Benar, 1, ...). Setelah loop keluar, lakukan loop 'induk' untuk memeriksa nilai itu. Biarkan saya menunjukkan:
Jika Anda memiliki loop tak terbatas, ini adalah satu-satunya jalan keluar; untuk eksekusi loop lainnya jauh lebih cepat. Ini juga berfungsi jika Anda memiliki banyak loop bersarang. Anda dapat keluar semua, atau hanya beberapa. Kemungkinan tak terbatas! Semoga ini bisa membantu!
sumber
Untuk keluar dari beberapa loop bersarang, tanpa refactoring ke fungsi, gunakan "pernyataan goto yang disimulasikan" dengan pengecualian StopIteration bawaan :
Lihat diskusi ini tentang penggunaan pernyataan goto untuk keluar dari loop bersarang.
sumber
atau semacam itu. Anda bisa mengatur variabel di loop dalam, dan memeriksanya di loop luar segera setelah loop dalam keluar, rusak jika perlu. Saya agak suka metode GOTO, asalkan Anda tidak keberatan menggunakan modul lelucon April Mop - ini bukan Pythonic, tapi itu masuk akal.
sumber
Ini bukan cara tercantik untuk melakukannya, tetapi menurut saya, ini cara terbaik.
Saya cukup yakin Anda bisa melakukan sesuatu menggunakan rekursi di sini juga, tapi saya tidak tahu apakah itu pilihan yang baik untuk Anda.
sumber
Dan mengapa tidak terus mengulang-ulang jika dua kondisi itu benar? Saya pikir ini adalah cara yang lebih pythonic:
Bukan?
Semua yang terbaik.
sumber
while dejaVu:
? Anda tetap menetapkannya menjadi benar.True
kondisi untuk melewatkan dua loop, tetapi hanya satu yang cukup.if not dejaVu: break
di bagian bawah dan dengan demikian keluar dari loop utama? Saya pikir solusinya paling dekat dengan apa yang diminta. +1Factor logika loop Anda menjadi sebuah iterator yang menghasilkan variabel loop dan kembali ketika selesai - berikut ini adalah yang sederhana yang menjabarkan gambar dalam baris / kolom sampai kita kehabisan gambar atau keluar dari tempat untuk meletakkannya:
Ini memiliki keuntungan memisahkan logika loop rumit dan pemrosesan ...
sumber
Dalam hal ini, sebagaimana ditunjukkan oleh orang lain juga, dekomposisi fungsional adalah cara yang harus dilakukan. Kode dalam Python 3:
sumber
Ada trik tersembunyi dalam
while ... else
struktur Python yang dapat digunakan untuk mensimulasikan double break tanpa banyak perubahan / penambahan kode. Intinya jikawhile
kondisinya salah,else
blok dipicu. Tidak ada pengecualian,continue
ataubreak
memicuelse
blokir. Untuk informasi lebih lanjut, lihat jawaban " Klausa lain pada pernyataan Python sementara ", atau dokumen Python sementara (v2.7) .Satu-satunya downside adalah bahwa Anda perlu memindahkan kondisi melanggar ganda ke dalam
while
kondisi (atau menambahkan variabel bendera). Variasi ini ada juga untukfor
loop, di manaelse
blok dipicu setelah loop selesai.sumber
How to break out of multiple loops in Python?
dan jawabannya seharusnya adalah "Tidak berhasil, coba yang lain". Saya tahu itu memperbaiki contoh yang diberikan dari OP, tetapi tidak menjawab pertanyaan mereka.Cara lain untuk mengurangi iterasi Anda menjadi satu tingkat loop akan melalui penggunaan generator seperti yang ditentukan dalam referensi python
Anda bisa meningkatkannya ke sejumlah level untuk loop
Kelemahannya adalah Anda tidak lagi dapat menembus hanya satu level. Semuanya atau tidak sama sekali.
Kelemahan lain adalah tidak bekerja dengan loop sementara. Saya awalnya ingin memposting jawaban ini dengan Python - `break` dari semua loop tetapi sayangnya itu ditutup sebagai duplikat dari yang ini
sumber
Alasan saya datang ke sini adalah saya memiliki loop luar dan loop dalam seperti:
Seperti yang Anda lihat, itu tidak akan benar-benar pergi ke x berikutnya, tetapi akan pergi ke y berikutnya.
apa yang saya temukan untuk menyelesaikan ini adalah menjalankan array dua kali sebagai gantinya:
Saya tahu ini adalah kasus spesifik dari pertanyaan OP, tetapi saya mempostingnya dengan harapan bahwa itu akan membantu seseorang memikirkan masalah mereka secara berbeda sambil menjaga hal-hal sederhana.
sumber
break
alih-alihcontinue
akan melakukan apa yang Anda inginkan, bukan? :-)Coba gunakan generator tanpa batas.
sumber
Dengan menggunakan fungsi:
Coba jalankan kode di atas dengan berkomentar
return
juga.Tanpa menggunakan fungsi apa pun:
Sekarang, jalankan kode di atas seperti yang pertama dan kemudian coba jalankan dengan mengomentari setiap baris yang berisi
break
satu per satu dari bawah.sumber
Cara mudah untuk mengubah banyak loop menjadi satu loop yang dapat diputuskan adalah dengan menggunakannya
numpy.ndindex
Anda memang harus mengindeks ke objek Anda, sebagai lawan untuk dapat beralih melalui nilai-nilai secara eksplisit, tetapi setidaknya dalam kasus-kasus sederhana tampaknya sekitar 2-20 kali lebih sederhana daripada sebagian besar jawaban yang disarankan.
sumber
sumber
mungkin sedikit trik seperti di bawah ini akan dilakukan jika tidak lebih suka refactorial menjadi fungsi
menambahkan 1 variabel break_level untuk mengontrol kondisi loop sementara
sumber
Anda dapat mendefinisikan variabel (misalnya break_statement ), kemudian mengubahnya ke nilai yang berbeda ketika kondisi dua-break terjadi dan menggunakannya dalam pernyataan if untuk break dari loop kedua juga.
sumber
Saya ingin mengingatkan Anda bahwa fungsi dalam Python dapat dibuat tepat di tengah kode dan dapat mengakses variabel sekitarnya secara transparan untuk membaca dan dengan
nonlocal
atauglobal
deklarasi untuk menulis.Jadi, Anda dapat menggunakan fungsi sebagai "struktur kontrol yang dapat dipecah", menentukan tempat Anda ingin kembali ke:
sumber
Solusi dalam 2 Cara
Dengan sebuah contoh: Apakah kedua matriks ini sama / sama?
matrix1 dan matrix2 memiliki ukuran yang sama, n, 2 matriks dimensi.
Solusi Pertama , tanpa fungsi
Solusi Kedua , dengan fungsi
Ini adalah solusi terakhir untuk kasus saya
Semoga harimu menyenangkan!
sumber
sumber
Semoga ini membantu:
sumber
Berikut ini adalah implementasi yang tampaknya berhasil:
Satu-satunya penarikan adalah bahwa Anda harus mendefinisikan
break_
sebelum loop.sumber
Kredit diberikan kepada Vivek Nagarajan, Programmer sejak 1987
Menggunakan Fungsi
Menggunakan bendera
sumber
Mirip seperti sebelumnya, tetapi lebih ringkas. (Booleans hanya angka)
sumber
Karena pertanyaan ini telah menjadi pertanyaan standar untuk membobol lingkaran tertentu, saya ingin memberikan jawaban saya dengan menggunakan contoh
Exception
.Meskipun tidak ada label yang bernama breaking of loop dalam konstruk yang dilipatgandakan secara berulang, kita dapat menggunakan Pengecualian Buatan Pengguna untuk memecah menjadi loop tertentu dari pilihan kita. Pertimbangkan contoh berikut di mana mari kita mencetak semua angka hingga 4 digit dalam sistem penomoran basis-6:
Ketika kita mencetak output, kita tidak akan pernah mendapatkan nilai yang unit place-nya dengan 4. Dalam hal itu, kita tidak putus dari loop apa pun seperti
BreakLoop(4)
dinaikkan dan ditangkap dalam loop yang sama. Demikian pula, setiap kali sepuluh tempat memiliki 3, kita masuk ke loop ketiga menggunakanBreakLoop(3)
. Setiap kali seratus tempat memiliki 5, kita masuk ke loop kedua menggunakanBreakLoop(2)
dan ketika ribuan tempat memiliki 2, kita masuk ke loop pertama menggunakanBreakLoop(1)
.Singkatnya, naikkan Pengecualian Anda (bawaan atau yang ditentukan pengguna) di loop bagian dalam, dan tangkap di loop dari tempat Anda ingin melanjutkan kontrol. Jika Anda ingin istirahat dari semua loop, tangkap Pengecualian di luar semua loop. (Saya belum menunjukkan kasus ini sebagai contoh).
sumber