วิธีออกจาก if clause


104

มีวิธีการอะไรบ้างสำหรับการออกจากไฟล์ ifประโยค ?

มีหลายครั้งที่ฉันกำลังเขียนโค้ดและต้องการใส่breakคำสั่งไว้ในifประโยคเพียงเพื่อจำไว้ว่าสิ่งเหล่านี้สามารถใช้ได้กับลูปเท่านั้น

ให้ใช้รหัสต่อไปนี้เป็นตัวอย่าง:

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

ฉันคิดวิธีหนึ่งในการทำเช่นนี้: สมมติว่ากรณีการออกเกิดขึ้นภายในคำสั่ง if ที่ซ้อนกันห่อรหัสที่เหลือในบล็อกขนาดใหญ่ ตัวอย่าง:

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

ปัญหานี้คือตำแหน่งทางออกที่มากขึ้นหมายถึงรหัสซ้อน / เยื้องมากขึ้น

อีกวิธีหนึ่งคือฉันสามารถเขียนโค้ดเพื่อให้ส่วนifคำสั่งมีขนาดเล็กที่สุดเท่าที่จะเป็นไปได้และไม่ต้องออก

ไม่มีใครรู้วิธีที่ดี / ดีกว่าในการออกจากifประโยค?

หากมีคำสั่ง else-if และ else ที่เกี่ยวข้องฉันคิดว่าการออกจะข้ามไป


2
สำหรับตัวอย่างโค้ดที่สองของคุณ - คุณรู้elifหรือไม่?
Craig McQueen

2
"หรืออีกวิธีหนึ่งคือฉันสามารถเขียนโค้ดของฉันเพื่อให้ส่วนคำสั่ง if มีขนาดเล็กที่สุดเท่าที่จะเป็นไปได้และไม่จำเป็นต้องมีทางออกใด ๆ " - และแน่นอนว่านี่จะเป็นแนวทางปฏิบัติที่ดีที่สุด :-)
Michał Marczyk

2
@ Craig McQueen: ฉันทำ แต่บอกว่าฉันต้องการให้โค้ดรันระหว่างเงื่อนไขเงื่อนไข? เช่นif a: #stuff; #stuff_inbetween; if b: #stuff;รหัส inbetween ขึ้นอยู่กับแต่ไม่ได้ขึ้นอยู่กับnot a b
โรมัน

สวัสดีโปรดอย่าลืมelif stackoverflow.com/a/2069680/7045119
kerbrose

คำตอบ:


99

(วิธีนี้ใช้ได้กับifs ลูปที่ซ้อนกันหลายตัวและโครงสร้างอื่น ๆ ที่คุณทำไม่ได้breakง่ายๆ)

ตัดโค้ดในฟังก์ชันของตัวเอง แทนที่จะbreakใช้return .

ตัวอย่าง:

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
ฉันยินดีที่จะเพิ่มเทคนิคโปรแกรมเมอร์ลงในกระเป๋าของคุณ จากประสบการณ์ของฉันวิธีนี้ใช้ได้ผลเกือบทุกครั้งที่คุณถูกล่อลวงให้ใช้ goto ที่เคลื่อนที่ไปข้างหน้า (และทั้งยังบอกใบ้และแก้ไขสถานการณ์ที่ฟังก์ชันเดียวมีขนาดใหญ่เกินไป)
Drew Dormann

2
ตามหลักการแล้วคุณสามารถบรรลุทั้งสองอย่างได้ แต่มีบางครั้งที่คุณต้องแลกเปลี่ยนรหัสที่ดีเพื่อประสิทธิภาพที่ดี เวลาเหล่านั้นหายากโดยเฉพาะอย่างยิ่งเมื่อคุณกำลังพิจารณาใช้ Python กล่าวอีกนัยหนึ่ง: อย่ากังวลกับค่าใช้จ่ายในการเรียกฟังก์ชันมากนัก
ephemient

17
มีเกร็ดเล็กเกร็ดน้อยเก่า ๆ : "Dennis Ritchie สนับสนุนความเป็นโมดูลาร์โดยบอกทุกคนว่าการเรียกใช้ฟังก์ชันนั้นราคาถูกมากใน C ทุกคนเริ่มเขียนฟังก์ชันขนาดเล็กและการแยกส่วนหลายปีต่อมาเราพบว่าการเรียกฟังก์ชันยังคงมีราคาแพงใน PDP-11 และรหัส VAX มักใช้เวลา 50% ในการสั่ง CALLS เดนนิสโกหกเรา! แต่มันสายไปแล้วพวกเราทุกคนติดยาเสพติด ... "
ephemient

1
@ephemient: ตลกดีมีอีกเรื่องไหม? ฉันต้องการอ่านเนื้อหาทั้งหมด
โรมัน

4
ใบเสนอราคานี้มาจากบทที่ 4 ของหนังสือ The Art of Unix Programming (ออนไลน์ที่faqs.org/docs/artu ) คุณควรอ่านเนื้อหาทั้งหมดหากคุณยังไม่เคยอ่านมาก่อน
ephemient

55
จากgotoนำเข้า goto ฉลาก

ถ้า some_condition:
   ...
   ถ้า condition_a:
       # ทำอะไรสักอย่าง
       # แล้วออกจากบล็อก if ด้านนอก
       goto .end
   ...
   ถ้า condition_b:
       # ทำอะไรสักอย่าง
       # แล้วออกจากบล็อก if ด้านนอก
       goto .end
   # รหัสเพิ่มเติมที่นี่

ป้ายกำกับ. end

(โปรดอย่าใช้สิ่งนี้จริง)


35
+1 เพราะนี่เป็นเรื่องตลก การค้นหาโดย Google เปิดเผยให้ฉันทราบว่านี่เป็นโมดูลเรื่องตลกของ April Fool
โรมัน

2
ฉันเชื่อมโยงกับมันด้วย gotoคลิกที่แรก
ephemient

1
สิ่งนี้ทำให้ฉันนึกถึงรหัสการประกอบที่มีการแตกแขนงทุกประเภท :)
phunehehe

2
@ephemient: อ่าไม่ได้สังเกตลิงค์ คิดว่ามันเป็นการเน้นรหัส แต่ตอนนี้ฉันดูโค้ดของคุณแล้วฉันไม่เห็นไฮไลต์ที่แท้จริงเกิดขึ้นเลย ..
โรมัน

1
เมื่อ PHP เปิดตัวไปฉันหันไปใช้ 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

3
โอ้ฉันชอบความคิดนี้มาก ฉันคิดว่านี่ช่วยแก้ความปรารถนาเดิมของฉันได้อย่างแน่นอน อย่างไรก็ตามฉันรู้สึกจู้จี้ว่านี่ไม่ใช่แนวทางปฏิบัติที่ดี (และด้วยเหตุนี้ฉันจะคงคำตอบที่ยอมรับในปัจจุบันไว้ในตอนนี้เพราะมันส่งเสริมรูปแบบการเข้ารหัสที่ดี)
โรมัน

6
โปรดทราบว่าคุณสามารถเก็บต้นฉบับถ้าและรวมสิ่งทั้งหมดไว้ในไฟล์while True:. อย่าลืมใส่breakคำสั่งในตอนท้าย! สำหรับภาษาที่มีโครงสร้าง do-while มันเป็นเรื่องปกติที่จะทำ:do { code that can conditionally break out } while (false);
Thomas Eding

10

คุณสามารถเลียนแบบการทำงานของ goto ได้โดยมีข้อยกเว้น:

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

ข้อจำกัดความรับผิดชอบ: ฉันหมายถึงเพียงแค่แจ้งให้คุณทราบถึงความเป็นไปได้ในการทำสิ่งต่างๆในลักษณะนี้ในขณะที่ฉันไม่รับรองว่าสมเหตุสมผลภายใต้สถานการณ์ปกติ ดังที่ฉันได้กล่าวไว้ในความคิดเห็นเกี่ยวกับคำถามการจัดโครงสร้างโค้ดเพื่อหลีกเลี่ยงเงื่อนไขแบบไบแซนไทน์ในตอนแรกนั้นเป็นที่นิยมมากกว่า :-)


ฮ่า ๆ ฉันชอบโซลูชันที่สร้างสรรค์นี้ แม้ว่าฉันจะปฏิบัติตามข้อจำกัดความรับผิดชอบของคุณและไม่ใช้รหัสขี้ขลาดเช่นนี้
โรมัน

@ โรมัน: มีความสุขที่ได้เพิ่มเคล็ดลับอื่น ๆ ควบคู่ไปกับ Shmoopty's - แม้ว่าฉันจะรู้สึกซนเมื่อเปรียบเทียบ ;-)
Michał Marczyk

8

อาจจะเป็น?

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
ใช่มันสามารถทำงานได้ ฉันคิดว่าจิตใจของelifฉันว่างเปล่าในขณะที่ฉันเขียนสิ่งนี้ แม้ว่าฉันคิดว่าสิ่งนี้จะใช้ไม่ได้ในสถานการณ์ที่ฉันต้องการให้โค้ดดำเนินการระหว่างคำสั่ง if ที่ซ้อนกัน
โรมัน

นี่คือคำตอบที่ถูกต้อง ทำไมไม่เห็นมีคนแนะนำ ?? :)
kerbrose

6

สำหรับสิ่งที่ถามจริงแนวทางของฉันคือทำให้ifs เหล่านั้นอยู่ในลูปแบบวนซ้ำ

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

ทดสอบ:

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
พูดตามตรงนี่เป็นวิธีแก้ปัญหาที่สะอาดที่สุด มันชัดเจนมากเมื่อรหัสจะออก - คุณไม่ต้องกังวลเกี่ยวกับการกำหนดขอบเขตฟังก์ชันภายในฟังก์ชันและไม่มีประสิทธิภาพหรือหนี้เชิงตรรกะ
เทรนต์

2
อาจพิจารณาใช้for _ in range(1):แทนwhile True:. (1) สื่อสารความตั้งใจของคุณเกี่ยวกับการวนซ้ำครั้งเดียวได้ดีขึ้นและ (2) ไม่มีคำสั่งหยุดพักสุดท้ายเพื่อออกจากลูป (อาจถูกลบออกโดยไม่ได้ตั้งใจในภายหลัง)
Bernhard Kausler

3

พูดโดยทั่วไปอย่า หากคุณกำลังทำ "ifs" และทำลายจากสิ่งเหล่านี้คุณกำลังทำผิด

อย่างไรก็ตามหากคุณต้อง:

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

หมายเหตุฟังก์ชั่นไม่ต้องประกาศในคำสั่ง if สามารถประกาศล่วงหน้าได้;) นี่จะเป็นทางเลือกที่ดีกว่าเนื่องจากจะหลีกเลี่ยงไม่ให้ต้อง refactor ออกมาเป็นสิ่งที่น่าเกลียดหาก / หลังจากนั้นในภายหลัง


ขอบคุณสำหรับคำตอบ. ฉันไม่แน่ใจว่าคุณหมายถึงอะไรโดย "การวนซ้ำ" หากคุณกำลังอ้างถึงการกล่าวถึงคำหลัก 'break' ของฉันฉันแค่พยายามกระตุ้นให้ฉันค้นหา if-exit โดยเปรียบเทียบกับการมีอยู่ของการออกแบบวนซ้ำ นอกจากนี้ฉันไม่แน่ใจว่าโค้ดของคุณแก้ปัญหาได้อย่างไรตามที่ตัวอย่างของฉันมีif condition_aและif condition_bซ้อนอยู่ภายในif some_conditionไฟล์. ฉันต้องการที่จะแยกออกจากไฟล์if some_condition.
โรมัน

สาเหตุที่ผู้คนต้องการสร้าง ifs และทำลายพวกเขาอาจไม่ใช่เพราะพวกเขาทำผิด แต่อาจเป็นเพราะพวกเขาต้องการเขียนโค้ดที่เรียบง่ายและสะอาด กรณีง่ายๆคือเมื่อโปรแกรมต้องทำ x () เมื่อทั้ง condition_a และ condition_b เป็นจริงและต้องทำ y () สำหรับ condition_a เท่านั้นและต้องทำ z () สำหรับ condition_b เท่านั้น และ coder ปฏิเสธที่จะเขียน x () หลายครั้ง
izzulmakin

1

สิ่งที่คุณกำลังอธิบายอย่างมีประสิทธิภาพคือข้อความ goto ซึ่งโดยทั่วไปจะมีการแพนค่อนข้างมาก ตัวอย่างที่สองของคุณเข้าใจง่ายกว่ามาก

อย่างไรก็ตามความสะอาดยังคงเป็น:

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

มีอีกวิธีหนึ่งที่ไม่ต้องพึ่งพาการกำหนดฟังก์ชัน (เพราะบางครั้งก็อ่านได้น้อยกว่าสำหรับข้อมูลโค้ดขนาดเล็ก) ไม่ได้ใช้ส่วนเสริมภายนอกในขณะที่วนซ้ำ (ซึ่งอาจต้องขอบคุณเป็นพิเศษในความคิดเห็นเพื่อให้เข้าใจได้ตั้งแต่แรกเห็น) ไม่ใช้ goto (... ) และที่สำคัญที่สุดให้คุณรักษาระดับการเยื้องไว้ด้านนอกถ้าเป็นเช่นนั้นคุณไม่ต้องเริ่มทำรัง

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

ใช่นั่นยังต้องการรูปลักษณ์ที่สองเพื่อความสามารถในการอ่านอย่างไรก็ตามหากตัวอย่างโค้ดมีขนาดเล็กสิ่งนี้ไม่จำเป็นต้องติดตามใด ๆ ในขณะที่ลูปที่จะไม่เกิดซ้ำและหลังจากเข้าใจว่า ifs ระดับกลางมีไว้เพื่ออะไรก็สามารถอ่านได้ง่ายทั้งหมดใน ที่เดียวและมีการเยื้องเดียวกัน

และควรมีประสิทธิภาพดี


0

ที่นี่ฉันเข้าใจว่าคุณกำลังพยายามแยกออกจากif code blockภายนอก

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

ทางออกหนึ่งคือคุณสามารถทดสอบเงื่อนไขเท็จในบล็อก if ด้านนอกซึ่งจะออกจากบล็อกโค้ดโดยปริยายจากนั้นคุณใช้บล็อกอื่นเพื่อซ้อน ifs อื่นเพื่อทำบางสิ่ง

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

สิ่งเดียวที่จะใช้สิ่งนี้โดยไม่มีวิธีการเพิ่มเติมคือelifตัวอย่างต่อไปนี้

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

นี่เป็นอีกวิธีในการจัดการปัญหานี้ ใช้รายการเดียวสำหรับการวนซ้ำที่ช่วยให้คุณสามารถใช้ต่อได้ ช่วยป้องกันความจำเป็นที่จะต้องมีฟังก์ชันพิเศษโดยไม่มีเหตุผล และยังกำจัดความไม่มีที่สิ้นสุดที่อาจเกิดขึ้นในขณะที่ลูป

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

ใช้returnในเงื่อนไข if จะทำให้คุณออกจากฟังก์ชันเพื่อให้คุณสามารถใช้ return เพื่อทำลายเงื่อนไข if


2
เขาต้องการที่จะทำลายถ้าไม่ออกจากฟังก์ชัน
StealthOne
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.