Cara keluar dari klausa if

104

Jenis metode apa yang ada untuk keluar sebelum waktunya dari ifklausa?

Ada kalanya saya menulis kode dan ingin meletakkan breakpernyataan di dalam ifklausa, hanya untuk diingat bahwa itu hanya dapat digunakan untuk loop.

Mari kita ambil kode berikut sebagai contoh:

if some_condition:
   ...
   if condition_a:
       # do something
       # and then exit the outer if block
   ...
   if condition_b:
       # do something
       # and then exit the outer if block
   # more code here

Saya dapat memikirkan satu cara untuk melakukan ini: dengan asumsi kasus keluar terjadi dalam pernyataan if bersarang, bungkus kode yang tersisa di blok lain yang besar. Contoh:

if some_condition:
   ...
   if condition_a:
       # do something
       # and then exit the outer if block
   else:
       ...
       if condition_b:
           # do something
           # and then exit the outer if block
       else:
           # more code here

Masalah dengan ini adalah bahwa lebih banyak lokasi keluar berarti lebih banyak kode bersarang / menjorok ke dalam.

Sebagai alternatif, saya dapat menulis kode saya agar ifklausa sekecil mungkin dan tidak perlu keluar.

Adakah yang tahu cara yang baik / lebih baik untuk keluar dari ifklausa?

Jika ada klausul else-if dan else terkait, saya pikir keluar akan melewatinya.

Roma
sumber
2
Untuk contoh kode kedua - tahukah Anda elif?
Craig McQueen
2
"Alternatifnya, saya dapat menulis kode saya agar klausa if menjadi sekecil mungkin dan tidak perlu keluar." - dan tentunya ini akan menjadi tindakan terbaik. :-)
Michał Marczyk
2
@Craig McQueen: Ya, tetapi saya ingin kode dieksekusi di antara pernyataan kondisi? Misalnya, if a: #stuff; #stuff_inbetween; if b: #stuff;kode peralihan bergantung pada not atetapi tidak bergantung pada b.
Roman
halo tolong jangan lupa elif stackoverflow.com/a/2069680/7045119
kerbrose

Jawaban:

99

(Metode ini berfungsi untuk ifs, beberapa loop bersarang, dan konstruksi lain yang tidak dapat Anda lakukan breakdengan mudah.)

Bungkus kode dalam fungsinya sendiri. Alih-alih break, gunakan return.

Contoh:

def some_function():
    if condition_a:
        # do something and return early
        ...
        return
    ...
    if condition_b:
        # do something else and return early
        ...
        return
    ...
    return

if outer_condition:
    ...
    some_function()
    ...
Drew Dormann
sumber
4
Saya dengan senang hati menambahkan trik programmer ke tas Anda. Dalam pengalaman saya, pendekatan itu bekerja hampir setiap kali Anda tergoda untuk menggunakan goto yang bergerak maju. (Dan keduanya mengisyaratkan dan mengatasi situasi di mana satu fungsi menjadi terlalu besar)
Drew Dormann
2
Idealnya Anda dapat mencapai keduanya, tetapi ada kalanya Anda harus menukar kode yang baik untuk kinerja yang baik. Saat-saat itu jarang terjadi, terutama ketika Anda mempertimbangkan untuk menggunakan Python. Dengan kata lain: jangan terlalu khawatir tentang overhead panggilan fungsi.
efemien
17
Ada anekdot lama: "Dennis Ritchie mendorong modularitas dengan memberi tahu semua orang bahwa panggilan fungsi benar-benar murah di C. Semua orang mulai menulis fungsi kecil dan modularisasi. Bertahun-tahun kemudian kami menemukan bahwa panggilan fungsi masih mahal di PDP-11 , dan kode VAX sering kali menghabiskan 50% waktunya dalam instruksi CALLS. Dennis telah berbohong kepada kami! Tapi sudah terlambat; kami semua ketagihan ... "
efemient
1
@ephemient: Itu lucu, apakah ceritanya lebih dari itu? Saya ingin membaca semuanya.
Roman
4
Kutipan ini berasal dari bab 4 dari buku The Art of Unix Programming (online di faqs.org/docs/artu ). Anda benar-benar harus membaca semuanya, jika Anda belum pernah membaca sebelumnya.
efemient
55
dari goto import goto, label

jika some_condition:
   ...
   jika condition_a:
       # lakukan sesuatu
       # dan kemudian keluar dari blok if luar
       goto .end
   ...
   jika condition_b:
       # lakukan sesuatu
       # dan kemudian keluar dari blok if luar
       goto .end
   # kode lainnya di sini

label .end

(Tolong jangan gunakan ini.)

singkat
sumber
35
+1 karena ini lucu. Pencarian google mengungkapkan kepada saya bahwa ini adalah modul lelucon April Mop.
Roman
2
Saya terhubung dengannya juga. Klik yang pertama goto.
efemient
1
ini mengingatkan saya pada kode assembly dengan semua jenis percabangan :)
phunehehe
2
@ephemient: Ah, tidak melihat tautannya. Pikir itu penyorotan kode. Tapi sekarang setelah saya melihat kode Anda, saya tidak melihat ada sorotan nyata yang terjadi ..
Roman
1
Ketika PHP memperkenalkan goto, saya beralih ke Python php.net/manual/en/control-structures.goto.php
Marc
25
while some_condition:
   ...
   if condition_a:
       # do something
       break
   ...
   if condition_b:
       # do something
       break
   # more code here
   break
Thomas Eding
sumber
3
Oh, hei, saya sangat suka ide ini. Saya pikir ini benar-benar menyelesaikan keinginan awal saya. Namun, saya memiliki perasaan yang mengganggu bahwa ini bukan praktik yang baik (dan karena alasan itu, saya akan mempertahankan jawaban yang diterima saat ini untuk saat ini karena mempromosikan gaya pengkodean yang baik).
Roman
6
Perhatikan bahwa Anda dapat menyimpan yang asli jika dan membungkus semuanya dalam file while True:. Pastikan untuk memasukkan breakpernyataan di akhir! Untuk bahasa dengan konstruksi do-while, itu lebih ideal untuk dilakukan:do { code that can conditionally break out } while (false);
Thomas Eding
10

Anda dapat meniru fungsionalitas goto dengan pengecualian:

try:
    # blah, blah ...
    # raise MyFunkyException as soon as you want out
except MyFunkyException:
    pass

Penafian: Saya hanya bermaksud memberi perhatian Anda kemungkinan melakukan hal-hal dengan cara ini, sementara saya sama sekali tidak mendukungnya sebagai hal yang masuk akal dalam keadaan normal. Seperti yang saya sebutkan dalam komentar tentang pertanyaan itu, menyusun kode untuk menghindari persyaratan Bizantium di tempat pertama lebih disukai sejauh ini. :-)

Michał Marczyk
sumber
Haha, saya suka solusi kreatif ini. Meskipun saya akan mematuhi disclaimer Anda dan tidak menggunakan kode yang funky seperti itu.
Roman
@Roman: Senang menambahkan trik lain bersama Shmoopty - bahkan ketika saya merasa nakal sebagai perbandingan. ;-)
Michał Marczyk
8

mungkin ini?

if some_condition and condition_a:
       # do something
elif some_condition and condition_b:
           # do something
           # and then exit the outer if block
elif some_condition and not condition_b:
           # more code here
else:
     #blah
if
anjing hantu74
sumber
1
Ya, itu bisa berhasil. Saya pikir pikiran saya agak kosong elifketika saya menulis ini. Meskipun saya pikir ini tidak akan berfungsi dalam situasi di mana saya ingin kode dijalankan di antara pernyataan if bersarang.
Roman
ini sebenarnya jawaban yang benar. mengapa saya tidak melihat orang merekomendasikan ini ?? :)
kerbrose
6

Untuk apa yang sebenarnya ditanyakan, pendekatan saya adalah menempatkannya ifdi dalam loop satu lingkaran

while (True):
    if (some_condition):
        ...
        if (condition_a):
            # do something
            # and then exit the outer if block
            break
        ...
        if (condition_b):
            # do something
            # and then exit the outer if block
            break
        # more code here
    # make sure it is looped once
    break

Menguji:

conditions = [True,False]
some_condition = True

for condition_a in conditions:
    for condition_b in conditions:
        print("\n")
        print("with condition_a", condition_a)
        print("with condition_b", condition_b)
        while (True):
            if (some_condition):
                print("checkpoint 1")
                if (condition_a):
                    # do something
                    # and then exit the outer if block
                    print("checkpoint 2")
                    break
                print ("checkpoint 3")
                if (condition_b):
                    # do something
                    # and then exit the outer if block
                    print("checkpoint 4")
                    break
                print ("checkpoint 5")
                # more code here
            # make sure it is looped once
            break
izzulmakin
sumber
1
Sejujurnya, ini adalah solusi terbersih. Sangat jelas kapan kode akan keluar - Anda tidak perlu khawatir tentang cakupan fungsi di dalam fungsi, dan tidak ada kinerja atau hutang logis.
Trent
2
Sebaiknya pertimbangkan untuk menggunakan for _ in range(1):daripada while True:. (1) Komunikasikan niat Anda dengan lebih baik tentang satu loop iterasi dan (2) tidak ada pernyataan jeda terakhir untuk keluar dari loop (mungkin terhapus secara tidak sengaja nanti)
Bernhard Kausler
3

Secara umum, jangan. Jika Anda bersarang "jika" dan memutuskannya, Anda melakukannya dengan salah.

Namun, jika Anda harus:

if condition_a:
   def condition_a_fun():
       do_stuff()
       if we_wanna_escape:
           return
   condition_a_fun()
if condition_b:
   def condition_b_fun():
       do_more_stuff()
       if we_wanna_get_out_again:
           return
   condition_b_fun()

Catatan, fungsi tidak HARUS dideklarasikan dalam pernyataan if, mereka dapat dideklarasikan sebelumnya;) Ini akan menjadi pilihan yang lebih baik, karena akan menghindari keharusan untuk merefaktor if / then yang jelek di kemudian hari.

Enki
sumber
Terima kasih atas jawabannya. Saya tidak yakin apa yang Anda maksud dengan 'loop bersarang'. Jika Anda mengacu pada penyebutan saya tentang kata kunci 'break', saya hanya mencoba memotivasi pencarian saya untuk if-exit dengan membandingkannya dengan keberadaan loop exit. Juga, saya tidak yakin bagaimana kode Anda memecahkan masalah, seperti contoh saya if condition_adan if condition_bbersarang di dalam file if some_condition. Saya ingin bisa keluar dari if some_condition.
Roman
Alasan orang ingin bersarang jika dan menghancurkannya mungkin bukan karena mereka salah melakukannya, tetapi mungkin karena mereka ingin menulis kode yang bersih sederhana dan KERING. Kasus sederhana adalah ketika program perlu melakukan x () ketika condition_a dan condition_b terpenuhi, dan perlu melakukan y () hanya untuk condition_a, dan perlu melakukan z () hanya untuk condition_b. dan pembuat kode menolak untuk menulis x () beberapa kali
izzulmakin
1

Secara efektif, apa yang Anda gambarkan adalah pernyataan kebagian, yang umumnya digeser cukup berat. Contoh kedua Anda jauh lebih mudah untuk dipahami.

Namun, pembersih tetap akan menjadi:

if some_condition:
   ...
   if condition_a:
       your_function1()
   else:
       your_function2()

...

def your_function2():
   if condition_b:
       # do something
       # and then exit the outer if block
   else:
       # more code here
Smashery
sumber
1

Ada cara lain yang tidak bergantung pada fungsi pendefinisian (karena terkadang itu kurang dapat dibaca untuk potongan kode kecil), tidak menggunakan loop sementara luar ekstra (yang mungkin membutuhkan apresiasi khusus dalam komentar bahkan untuk dapat dimengerti pada pandangan pertama) , tidak menggunakan goto (...) dan yang paling penting mari kita pertahankan tingkat indentasi Anda untuk bagian luar jika jadi Anda tidak perlu memulai hal-hal bersarang.

if some_condition:
   ...
   if condition_a:
       # do something
       exit_if=True # and then exit the outer if block
if some condition and not exit_if: # if and only if exit_if wasn't set we want to execute the following code
   # keep doing something
   if condition_b:
       # do something
       exit_if=True # and then exit the outer if block
if some condition and not exit_if:
   # keep doing something

Ya, itu juga membutuhkan pandangan kedua untuk keterbacaan, namun, jika cuplikan kodenya kecil, ini tidak perlu melacak loop sementara yang tidak akan pernah berulang dan setelah memahami untuk apa perantara itu, itu mudah dibaca, semua masuk satu tempat dan dengan lekukan yang sama.

Dan itu seharusnya cukup efisien.

DonQuiKong
sumber
0

Jadi di sini saya mengerti Anda mencoba untuk keluar dari blok kode if luar

if some_condition:
    ...
    if condition_a:
       # do something
       # and then exit the outer if block
       ...
    if condition_b:
       # do something
       # and then exit the outer if block
# more code here

Salah satu jalan keluarnya adalah Anda dapat menguji kondisi palsu di blok if luar, yang kemudian secara implisit keluar dari blok kode, Anda kemudian menggunakan blok lain untuk menyarangkan if lainnya untuk melakukan sesuatu.

if test_for_false:
    # Exit the code(which is the outer if code)

else:
    if condition_a:
        # Do something

    if condition_b:
        # Do something
Romeo
sumber
0

Satu-satunya hal yang akan menerapkan ini tanpa metode tambahan adalah elifsebagai contoh berikut

a = ['yearly', 'monthly', 'quartly', 'semiannual', 'monthly', 'quartly', 'semiannual', 'yearly']
# start the condition
if 'monthly' in b: 
    print('monthly') 
elif 'quartly' in b: 
    print('quartly') 
elif 'semiannual' in b: 
    print('semiannual') 
elif 'yearly' in b: 
    print('yearly') 
else: 
    print('final') 
kerbrose.dll
sumber
-1

Berikut cara lain untuk mengatasinya. Ini menggunakan satu item untuk loop yang memungkinkan Anda untuk hanya menggunakan lanjutkan. Ini mencegah kebutuhan yang tidak perlu untuk memiliki fungsi tambahan tanpa alasan. Dan juga menghilangkan potensi loop tidak terbatas.

if something:
    for _ in [0]:
        # Get x
        if not x:
            continue

        # Get y
        if not y:
            continue

        # Get z
        if not z:
            continue

        # Stuff that depends on x, y, and z
Timbot
sumber
-2

gunakan returnjika kondisi akan mengembalikan Anda keluar dari fungsi, sehingga Anda bisa menggunakan kembali untuk memutus kondisi if.

Nikhil Parashar
sumber
2
dia ingin menghentikan jika tidak keluar dari fungsi
StealthOne