Bir if cümlesinden nasıl çıkılır


104

Bir ifmaddeden erken çıkmak için ne tür yöntemler vardır ?

Kod yazdığım ve bir breakcümlenin içine bir ifade koymak istediğim zamanlar vardır if, sadece bunların yalnızca döngüler için kullanılabileceğini hatırlamak için.

Örnek olarak aşağıdaki kodu alalım:

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

Bunu yapmanın bir yolunu düşünebilirim: çıkış durumlarının iç içe geçmiş if ifadeleri içinde gerçekleştiğini varsayarak, kalan kodu başka bir büyük bloğa sarın. Misal:

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

Bununla ilgili sorun, daha fazla çıkış konumunun daha fazla iç içe / girintili kod anlamına gelmesidir.

Alternatif olarak, ifcümleciklerin olabildiğince küçük olması ve herhangi bir çıkış gerektirmemesi için kodumu yazabilirim .

Bir ifmaddeden çıkmanın iyi / daha iyi bir yolunu bilen var mı ?

Herhangi bir ilişkili else-if ve else cümleleri varsa, çıkışın onları atlayacağını düşünüyorum.


2
İkinci kod örneğiniz için - biliyor musunuz elif?
Craig McQueen

2
"Alternatif olarak, if cümlelerinin olabildiğince küçük olması ve herhangi bir çıkış gerektirmemesi için kodumu yazabilirim." - ve elbette bu en iyi hareket tarzı olacaktır. :-)
Michał Marczyk

2
@Craig McQueen: Yapıyorum ama şart ifadeleri arasında kod çalıştırılmasını istediğimi söylüyorum? Örneğin if a: #stuff; #stuff_inbetween; if b: #stuff;, aradaki kod bağlıdır, not aancak buna bağlı değildir b.
Roman

Yanıtlar:


99

(Bu yöntem if, birden çok iç içe geçmiş döngü ve breakkolayca yapamayacağınız diğer yapılar için çalışır .)

Kodu kendi işlevine sarın. Bunun yerine breakkullanın return.

Misal:

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()
    ...

4
Programcı hileler çantanıza eklemekten mutluluk duyuyorum. Tecrübelerime göre, bu yaklaşım, ileriye doğru hareket etmeye meyilli olduğunuz her seferinde işe yarar. (Ve tek bir işlevin çok
büyüdüğü

2
İdeal olarak her ikisini de başarabilirsiniz, ancak iyi performans için iyi kod ticareti yapmanız gereken zamanlar vardır. Bu zamanlar, özellikle Python kullanmayı düşündüğünüzde nadirdir. Başka bir deyişle: işlev çağrısı ek yükü hakkında çok fazla endişelenmeyin.
17:47

17
Eski bir anekdot var: "Dennis Ritchie, C'de işlev çağrılarının gerçekten çok ucuz olduğunu söyleyerek modülerliği teşvik etti. Herkes küçük işlevler yazmaya ve modülerleştirmeye başladı. Yıllar sonra, işlev çağrılarının PDP-11'de hala pahalı olduğunu öğrendik. ve VAX kodu zamanının% 50'sini ÇAĞRI talimatlarında geçiriyordu. Dennis bize yalan söylemişti! Ama artık çok geçti; hepimiz
bağlıydık

1
@ephemient: Bu komik, hikayede daha fazlası var mı? Her şeyi okumak istiyorum.
Roman

4
Bu alıntı, The Art of Unix Programming kitabının 4. bölümünden alınmıştır ( faqs.org/docs/artu adresinde çevrimiçi ). Daha önce okumadıysanız, gerçekten her şeyi okumalısınız.
ephemient

55
dan git ithalat git, etiket

bazı_şartlar:
   ...
   koşul_a:
       # bir şey yap
       # ve sonra dış if bloğundan çıkın
       goto .end
   ...
   eğer koşul_b:
       # bir şey yap
       # ve sonra dış if bloğundan çıkın
       goto .end
   # kod daha burada

label .end

(Lütfen bunu kullanmayın.)


35
+1 çünkü bu komik. Bir Google araması bana bunun bir Nisan Şakası şaka modülü olduğunu ortaya çıkardı.
Roman

2
Ben de ona bağlandım. Birincisine tıklayın goto.
17:42

1
bu bana her türlü dallanma ile montaj kodunu hatırlatıyor :)
phunehehe

2
@ephemient: Ah, bağlantıyı fark etmedim. Kod vurgulama olduğunu anladım. Ama şimdi kodunuza baktığıma göre, gerçek bir vurgu görmüyorum ..
Roman


25
while some_condition:
   ...
   if condition_a:
       # do something
       break
   ...
   if condition_b:
       # do something
       break
   # more code here
   break

3
Oh, hey, bu fikri gerçekten beğendim. Sanırım bu tam olarak benim asıl arzumu çözüyor. Bununla birlikte, bunun iyi bir uygulama olmadığına dair rahatsız edici bir his var (ve bu nedenle, iyi kodlama stilini desteklediği için şimdilik kabul edilen mevcut yanıtı koruyacağım).
Roman

6
Orijinali saklayabileceğinizi ve her şeyi bir while True:. Sadece breaksonunda bir açıklama yazdığınızdan emin olun ! Do-while yapısına sahip diller için aşağıdakileri yapmak daha idomatiktir:do { code that can conditionally break out } while (false);
Thomas Eding

10

Goto'nun işlevselliğini istisnalarla taklit edebilirsiniz:

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

Sorumluluk Reddi: Sadece dikkatinizi bir şeyleri bu şekilde yapma olasılığına getirmek istiyorum , ancak hiçbir şekilde normal koşullar altında makul olduğunu onaylamıyorum. Soruyla ilgili bir yorumda bahsettiğim gibi, kodun ilk etapta Bizans koşullarından kaçınacak şekilde yapılandırılması açık ara tercih edilir. :-)


Haha, bu yaratıcı çözümü beğendim. Yine de feragatnamenize uyacağım ve bu kadar acayip kod kullanmayacağım.
Roman

@Roman: Shmoopty'nin yanına başka bir numara eklemekten mutluluk duyuyorum - buna kıyasla kendimi yaramaz hissetsem bile. ;-)
Michał Marczyk

8

belki bu?

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

1
Evet, işe yarayabilir. Sanırım bunu elifyazarken zihnim boşa gitti . Bunun, kodun iç içe geçmiş if ifadeleri arasında yürütülmesini istediğim bir durumda işe yaramayacağını düşünmeme rağmen.
Roman

bu aslında doğru cevap. neden insanların bunu tavsiye ettiğini görmüyorum ?? :)
kerbrose

6

Gerçekte sorulan şey için, benim yaklaşımım bunları iftek döngülü bir döngünün içine koymak

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

Dene:

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

1
Dürüst olmak gerekirse, bu en temiz çözüm. Kodun ne zaman çıkacağı çok açık - işlevlerin içindeki işlev kapsamını belirleme konusunda endişelenmenize gerek yok ve sıfır performans veya mantıksal borç var.
Trent

2
for _ in range(1):Bunun yerine kullanmayı düşünebilirsiniz while True:. (1) Tek bir yineleme döngüsü niyetinizi daha iyi
iletin

3

Genel olarak konuşmayın. Eğer "eğerler" i iç içe geçiriyor ve onlardan kopuyorsanız, yanlış yapıyorsunuz demektir.

Ancak, yapmanız gerekiyorsa:

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()

Unutmayın, işlevlerin if deyiminde bildirilmesi ZORUNLUDUR, önceden bildirilebilirler;) Bu daha iyi bir seçimdir, çünkü daha sonra çirkin bir durumu yeniden düzenleme gereksinimini ortadan kaldıracaktır.


Cevap için teşekkürler. 'İç içe geçmiş döngü' ile ne demek istediğinden emin değilim. Eğer 'ara' anahtar kelimesinden bahsetmeme atıfta bulunuyorsanız, sadece bir if-çıkışı aramamı onu bir döngü çıkışının varlığıyla karşılaştırarak motive etmeye çalışıyordum. Benim örnek vardı kodunuzu, sorunu nasıl çözdüğünü Ayrıca emin oldum if condition_ave if condition_bbir iç içe if some_condition. 'Dan kaçabilmek istiyorum if some_condition.
Roman

İnsanların ifs ve onları kırmak istemelerinin nedeni muhtemelen yanlış yaptıkları için değil, belki de temiz, basit ve DRY kod yazmak istemeleridir. Basit durum, programın hem koşul_a hem de koşul_b yerine getirildiğinde x () yapması gerektiği ve yalnızca koşul_a için y () yapması gerektiği ve yalnızca koşul_b için z () yapması gerektiği durumdur. ve kodlayıcı x () birden çok kez yazmayı reddediyor
izzulmakin

1

Etkili bir şekilde açıkladığınız şey, genellikle oldukça yoğun bir şekilde kaydırılan goto ifadeleridir. İkinci örneğinizin anlaşılması çok daha kolay.

Ancak, temizleyici yine de:

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

1

İşlevleri tanımlamaya dayanmayan başka bir yol daha vardır (çünkü bazen bu küçük kod parçacıkları için daha az okunabilirdir), fazladan bir dış while döngüsü kullanmaz (ilk bakışta bile anlaşılabilir olması için yorumlarda özel takdir gerektirebilir) , goto (...) kullanmaz ve en önemlisi, dış için girinti düzeyinizi korumanıza izin verin, böylece iç içe geçirmeye başlamanız gerekmez.

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

Evet, bu aynı zamanda okunabilirlik için ikinci bir bakıma da ihtiyaç duyar, ancak, eğer kod parçacıkları küçükse, bu hiçbir zaman tekrar etmeyecek süre döngülerini izlemenizi gerektirmez ve ara iflerin ne işe yaradığını anladıktan sonra kolayca okunabilir, hepsi içinde bir yerde ve aynı girintiyle.

Ve oldukça verimli olmalı.


0

Yani burada anladığım kadarıyla dış if kod bloğundan çıkmaya çalışıyorsunuz

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

Bundan kurtulmanın bir yolu, dış if bloğunda yanlış bir koşul için test yapabilmenizdir, bu daha sonra kod bloğundan dolaylı olarak çıkacaktır, daha sonra bir şey yapmak için diğerini iç içe geçirmek için başka bir blok kullanırsınız.

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

else:
    if condition_a:
        # Do something

    if condition_b:
        # Do something

0

Bunu ek yöntemler olmadan uygulayacak tek şey elifaşağıdaki örnektir.

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') 

-1

İşte bunu halletmenin başka bir yolu. Devam et seçeneğini kullanmanızı sağlayan tek bir öğe for döngüsü kullanır. Gereksiz ekstra fonksiyonlara sahip olma ihtiyacını sebepsiz yere engeller. Ayrıca potansiyel sonsuz döngüleri ortadan kaldırır.

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

-2

returnif koşulunda kullanmak sizi işlevden döndürür, böylece if koşulunu bozmak için return kullanabilirsiniz.


2
işlevden çıkmak değilse de bozmak istiyor
StealthOne
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.