Python ลองอย่างอื่น


579

การใช้เจตนาของelseอนุประโยคทางเลือกของtryคำสั่งคืออะไร?


1
คำตอบส่วนใหญ่ดูเหมือนจะเน้นว่าทำไมเราไม่สามารถใส่เนื้อหาลงในประโยคอื่นในประโยคลองได้ด้วยตัวเอง คำถามstackoverflow.com/questions/3996329ถามเป็นพิเศษว่าทำไมรหัสข้ออื่นไม่สามารถไปได้หลังจากลองบล็อกตัวเองและคำถามนั้นเป็นคำถามนี้ แต่ฉันไม่เห็นคำตอบที่ชัดเจนของคำถามนี้ ฉันรู้สึกstackoverflow.com/a/3996378/1503120ตอบคำถามได้อย่างยอดเยี่ยม ฉันยังได้พยายามที่จะชี้ให้เห็นความสำคัญต่าง ๆ ของคำสั่งต่างๆที่stackoverflow.com/a/22579805/1503120
jamadagni

คุณต้องการให้มีบางสิ่งเกิดขึ้นถ้าข้อยกเว้นไม่ทริกเกอร์ก่อนการล้างข้อมูลครั้งสุดท้ายซึ่งไม่ควรทริกเกอร์การจัดการข้อยกเว้นเดียวกัน
benjimin

คำตอบ:


857

คำสั่งในelseบล็อกจะถูกดำเนินการหากการดำเนินการล้มลงด้านล่างของtry- หากไม่มีข้อยกเว้น สุจริตฉันไม่เคยพบความต้องการ

อย่างไรก็ตามการจัดการข้อยกเว้น :

การใช้อนุประโยคอื่นดีกว่าการเพิ่มรหัสเพิ่มเติมลงใน try clause เนื่องจากจะหลีกเลี่ยงการจับยกเว้นที่ไม่ได้เกิดจากโค้ดที่ได้รับการปกป้องโดยคำสั่ง try ... ยกเว้นโดยไม่ได้ตั้งใจ

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

try:
    operation_that_can_throw_ioerror()
except IOError:
    handle_the_exception_somehow()
else:
    # we don't want to catch the IOError if it's raised
    another_operation_that_can_throw_ioerror()
finally:
    something_we_always_need_to_do()

หากคุณเพียงแค่ใส่another_operation_that_can_throw_ioerror()หลังจากoperation_that_can_throw_ioerrorที่exceptจะจับความผิดพลาดของสายที่สอง และถ้าคุณใส่มันหลังจากที่ทั้งบล็อกก็จะมักจะถูกเรียกใช้และไม่ได้จนกว่าหลังจากที่try ช่วยให้คุณสามารถตรวจสอบให้แน่ใจfinallyelse

  1. การดำเนินการที่สองจะทำงานต่อเมื่อไม่มีข้อยกเว้น
  2. มันทำงานก่อนfinallyบล็อกและ
  3. สิ่งใด ๆ ที่IOErrorเกิดขึ้นไม่ได้ถูกจับที่นี่

7
โปรดทราบว่าตัวแปรที่ใช้ในบล็อกลองสามารถใช้ในบล็อกอื่นได้ดังนั้นคุณควรพิจารณาใช้ตัวแปรนี้หากคุณไม่คาดหวังว่าจะมีข้อยกเว้นเพิ่มเติมในบล็อกอื่น
WorldSEnder

3
ไม่สำคัญเนื่องจากตัวแปรที่กำหนดขอบเขตแบบลองถูกมองเห็นนอกการทดลองไม่ว่าจะมีตัวแปรอื่นหรือไม่ก็ตาม
Reinderien

36
ไม่มีสิ่งเช่น "ตัวแปรทดลองที่กำหนดขอบเขต" ใน Python ขอบเขตของตัวแปรถูกสร้างขึ้นโดยโมดูลฟังก์ชันและความเข้าใจเท่านั้นไม่ใช่โครงสร้างการควบคุม
mhsmith

9
ประโยคอื่นให้คุณเขียนโค้ดที่เหมาะสมถ้าไม่มีข้อยกเว้นเกิดขึ้น ข้อยกเว้นสามารถผ่านได้ง่าย หากคุณใส่ตรรกะในบล็อกลองคุณมีความเสี่ยงซ่อนข้อบกพร่องในรหัสของคุณ อย่าสควอชข้อยกเว้นที่คุณไม่คาดคิด
อลิซเพอร์เซลล์

9
มันจะไม่ชัดเจนจากคำตอบนี้ว่า"ตกลงไปด้านล่าง"หมายถึง - ไม่เพียง แต่เรื่องนี้เกิดขึ้นเนื่องจากมีข้อยกเว้น แต่ยังเพราะของreturn, หรือcontinue break
Antti Haapala

108

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

try:
    from EasyDialogs import AskPassword
    # 20 other lines
    getpass = AskPassword
except ImportError:
    getpass = default_getpass

และ

try:
    from EasyDialogs import AskPassword
except ImportError:
    getpass = default_getpass
else:
    # 20 other lines
    getpass = AskPassword

ส่วนที่สองนั้นดีเมื่อexceptไม่สามารถกลับมาก่อนได้หรือส่งข้อยกเว้นอีกครั้ง ถ้าเป็นไปได้ฉันจะเขียนว่า:

try:
    from EasyDialogs import AskPassword
except ImportError:
    getpass = default_getpass
    return False  # or throw Exception('something more descriptive')

# 20 other lines
getpass = AskPassword

หมายเหตุ:คำตอบที่คัดลอกมาจากโพสต์เมื่อเร็ว ๆ นี้ซ้ำกันที่นี่จึงทุกสิ่ง "AskPassword"


53

ใช้เพียงครั้งเดียว: ทดสอบโค้ดบางอย่างที่ควรเพิ่มข้อยกเว้น

try:
    this_should_raise_TypeError()
except TypeError:
    pass
except:
    assert False, "Raised the wrong exception type"
else:
    assert False, "Didn't raise any exception"

(รหัสนี้ควรจะถูกนำไปใช้ในการทดสอบทั่วไปมากขึ้นในทางปฏิบัติ)


50

Python ลองอย่างอื่น

การใช้elseประโยคคำสั่งเผื่อเลือกของคำสั่ง try คืออะไร?

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

บริบทนี้หลีกเลี่ยงการจัดการข้อผิดพลาดที่คุณไม่คาดคิด

แต่มันเป็นสิ่งสำคัญที่จะเข้าใจเงื่อนไขแม่นยำว่าสาเหตุประโยคอื่นที่จะทำงานเพราะreturn, continueและสามารถหยุดการไหลของการควบคุมbreakelse

สรุป

elseคำสั่งทำงานถ้ามีไม่มีข้อยกเว้นและหากไม่ขัดจังหวะด้วยreturn, continueหรือbreakคำสั่ง

คำตอบอื่น ๆ ที่คิดถึงส่วนสุดท้าย

จากเอกสาร:

elseประโยคที่เป็นตัวเลือกจะถูกดำเนินการถ้าและเมื่อการควบคุมไหลออกจากส่วนท้ายของtryข้อ *

(เพิ่ม Bolding แล้ว) และเชิงอรรถอ่านว่า:

* ปัจจุบันการควบคุม“ไหลปิดท้าย” ยกเว้นในกรณีที่มีข้อยกเว้นหรือการดำเนินการที่return, continueหรือbreakคำสั่ง

มันต้องการอย่างน้อยหนึ่งก่อนหน้ายกเว้นข้อ ( ดูไวยากรณ์ ) ดังนั้นมันจึงไม่ใช่ "ลอง - อื่น" คือ "ลอง - ยกเว้น - อื่น ๆ (- สุดท้าย)" โดยที่else(และfinally) เป็นตัวเลือก

หลามสอน elaborates กับการใช้งานที่ตั้งใจไว้:

คำสั่งลอง ... ยกเว้นมีประโยคอื่นที่เป็นทางเลือกซึ่งเมื่อมีอยู่ต้องปฏิบัติตามข้อยกเว้นทั้งหมด มันจะมีประโยชน์สำหรับรหัสที่จะต้องดำเนินการหากมาตราประโยคลองไม่ยกข้อยกเว้น ตัวอย่างเช่น:

for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except IOError:
        print 'cannot open', arg
    else:
        print arg, 'has', len(f.readlines()), 'lines'
        f.close()

การใช้อนุประโยคอื่นดีกว่าการเพิ่มรหัสเพิ่มเติมลงใน try clause เนื่องจากจะหลีกเลี่ยงการจับยกเว้นที่ไม่ได้เกิดจากโค้ดที่ได้รับการปกป้องโดยคำสั่ง try ... ยกเว้นโดยไม่ได้ตั้งใจ

ตัวอย่างที่แตกต่างelseกับรหัสติดตามtryบล็อก

หากคุณจัดการกับข้อผิดพลาดelseบล็อกจะไม่ทำงาน ตัวอย่างเช่น:

def handle_error():
    try:
        raise RuntimeError('oops!')
    except RuntimeError as error:
        print('handled a RuntimeError, no big deal.')
    else:
        print('if this prints, we had no error!') # won't print!
    print('And now we have left the try block!')  # will print!

และตอนนี้,

>>> handle_error()
handled a RuntimeError, no big deal.
And now we have left the try block!

26

ลองใช้ข้อยกเว้นที่ดีสำหรับการรวมรูปแบบ EAFP เข้ากับการพิมพ์เป็ด :

try:
  cs = x.cleanupSet
except AttributeError:
  pass
else:
  for v in cs:
    v.cleanup()

คุณอาจสิ่งที่รหัสไร้เดียงสานี้ใช้ได้:

try:
  for v in x.cleanupSet:
    v.clenaup()
except AttributeError:
  pass

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


19

ฉันพบว่ามีประโยชน์จริง ๆ เมื่อคุณล้างข้อมูลที่ต้องทำแม้ว่าจะมีข้อยกเว้น:

try:
    data = something_that_can_go_wrong()
except Exception as e: # yes, I know that's a bad way to do it...
    handle_exception(e)
else:
    do_stuff(data)
finally:
    clean_up()

9

แม้ว่าคุณจะไม่สามารถคิดถึงการใช้งานได้ในตอนนี้ แต่คุณสามารถเดิมพันได้ว่าจะต้องมีการใช้งาน นี่คือตัวอย่างที่ไร้จินตนาการ:

ด้วยelse:

a = [1,2,3]
try:
    something = a[2]
except:
    print "out of bounds"
else:
    print something

โดยไม่ต้องelse:

try:
    something = a[2]
except:
    print "out of bounds"

if "something" in locals():
    print something

ที่นี่คุณมีตัวแปรที่somethingกำหนดไว้หากไม่มีข้อผิดพลาดเกิดขึ้น คุณสามารถนำสิ่งนี้ออกนอกtryบล็อกได้ แต่ต้องมีการตรวจจับยุ่งเหยิงหากกำหนดตัวแปรไว้


3
เกิดอะไรขึ้นกับsomething = a[2]; print somethingการลอง: บล็อก
S.Lott

@ S.Lott ไม่มีอะไร แต่ถ้ามีใครส่งรายการให้คุณและคุณไม่ต้องการแสดงข้อมูลถ้ามันไม่นานพอเพราะมันอาจจะเสียหาย?
ไม่ทราบ

12
S. Lott: 'พิมพ์บางอย่าง' อาจทำให้เกิดข้อยกเว้นอื่นที่คุณไม่ต้องการสกัดกั้น
Darius Bacon

ฉันไม่เห็นความแตกต่าง ถ้าฉันได้รับการยกเว้นนอกขอบเขตมันจะพิมพ์ "เกินขอบเขต" ได้ที่ หากฉันได้รับข้อยกเว้นอื่น ๆ จะไม่มีการตรวจจับโดยรหัสบล็อกนี้ ถ้าฉันไม่ได้รับการยกเว้นพฤติกรรมคือการพิมพ์ค่าของบางสิ่งซึ่งก็คือ [2] ฉันไม่เห็นสิ่งอื่นในตัวอย่างนี้
S.Lott

3
ค่าของ 'บางสิ่ง' เมื่อพิมพ์อาจทำให้เกิดข้อผิดพลาดในวิธี __str __ () ในขณะที่ค่านั้นเป็นเพียง 2 ในตัวอย่างนี้คุณก็อาจชี้ให้เห็นว่าไม่มีข้อยกเว้นนอกขอบเขตที่นี่เช่นกัน
Darius Bacon

8

มีตัวอย่างที่ดีของการเป็นtry-elseในPEP 380 โดยพื้นฐานแล้วการจัดการข้อยกเว้นที่แตกต่างกันในส่วนต่างๆของอัลกอริทึม

มันเป็นแบบนี้:

try:
    do_init_stuff()
except:
    handle_init_suff_execption()
else:
    try:
        do_middle_stuff()
    except:
        handle_middle_stuff_exception()

สิ่งนี้ช่วยให้คุณสามารถเขียนรหัสการจัดการข้อยกเว้นใกล้กับข้อยกเว้นที่เกิดขึ้น


7

จากข้อผิดพลาดและข้อยกเว้น # การจัดการข้อยกเว้น - docs.python.org

try ... exceptคำสั่งมีตัวเลือกelseข้อซึ่งเมื่อปัจจุบันจะต้องปฏิบัติตามคำสั่งทั้งหมดยกเว้น มันจะมีประโยชน์สำหรับรหัสที่จะต้องดำเนินการหากมาตราประโยคลองไม่ยกข้อยกเว้น ตัวอย่างเช่น:

for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except IOError:
        print 'cannot open', arg
    else:
        print arg, 'has', len(f.readlines()), 'lines'
        f.close()

การใช้อนุประโยคอื่นดีกว่าการเพิ่มรหัสเพิ่มเติมลงใน try clause เนื่องจากจะหลีกเลี่ยงการจับยกเว้นที่ไม่ได้เกิดจากโค้ดที่ได้รับการปกป้องโดยคำสั่ง try ... ยกเว้นโดยไม่ได้ตั้งใจ


6

ดูที่การอ้างอิงของ Pythonดูเหมือนว่าelseจะถูกดำเนินการหลังจากที่tryไม่มีข้อยกเว้น ส่วนคำสั่งอื่นเป็นตัวเลือกจะดำเนินการถ้าและเมื่อการควบคุมไหลออกจากส่วนท้ายของข้อลอง 2ข้อยกเว้นในข้ออื่นไม่ได้รับการจัดการโดยข้อยกเว้นก่อนหน้านี้

ดำน้ำใน pythonมีตัวอย่างที่ถ้าฉันเข้าใจถูกต้องในtryบล็อกพวกเขาพยายามที่จะนำเข้าโมดูลเมื่อที่ล้มเหลวคุณจะได้รับข้อยกเว้นและผูกเริ่มต้น แต่เมื่อมันทำงานคุณมีตัวเลือกที่จะเข้าสู่elseบล็อกและผูกสิ่งที่จำเป็น (ดู ลิงค์สำหรับตัวอย่างและคำอธิบาย)

หากคุณพยายามที่จะทำงานในcatchบล็อกมันอาจทำให้เกิดข้อยกเว้นอื่น - ฉันคิดว่านั่นคือสิ่งที่elseบล็อกมีประโยชน์


4
"ข้อยกเว้นในข้ออื่นไม่ได้รับการจัดการโดยข้อยกเว้นก่อนหน้านี้" นั่นคือส่วนที่มีประโยชน์ ขอบคุณ.
geowa4

"ส่วนคำสั่งทางเลือกอื่นจะดำเนินการถ้าและเมื่อการควบคุมการไหลออกจากส่วนท้ายของข้อลอง" เป็นความแตกต่างอื่นเนื่องจากคุณสามารถกลับออกจากtryบล็อก
Tomer W

4

แค่นั้นแหละ. บล็อก 'else' ของ try-except clause มีอยู่สำหรับโค้ดที่รันเมื่อ (และเมื่อ) การดำเนินการที่พยายามสำเร็จ มันสามารถนำมาใช้และมันสามารถถูกทารุณกรรม

try:
    fp= open("configuration_file", "rb")
except EnvironmentError:
    confdata= '' # it's ok if the file can't be opened
else:
    confdata= fp.read()
    fp.close()

# your code continues here
# working with (possibly empty) confdata

ส่วนตัวผมชอบมันและใช้งานได้ตามความเหมาะสม มันจัดกลุ่มคำสั่ง


2

บางทีการใช้อาจเป็น:

#debug = []

def debuglog(text, obj=None):
    " Simple little logger. "
    try:
        debug   # does global exist?
    except NameError:
        pass    # if not, don't even bother displaying
    except:
        print('Unknown cause. Debug debuglog().')
    else:
        # debug does exist.
        # Now test if you want to log this debug message
        # from caller "obj"
        try:
            if obj in debug:
                print(text)     # stdout
        except TypeError:
            print('The global "debug" flag should be an iterable.')
        except:
            print('Unknown cause. Debug debuglog().')

def myfunc():
    debuglog('Made it to myfunc()', myfunc)

debug = [myfunc,]
myfunc()

บางทีนี่อาจจะนำคุณไปใช้เช่นกัน


2

ฉันได้พบtry: ... else:โครงสร้างที่มีประโยชน์ในสถานการณ์ที่คุณกำลังเรียกใช้แบบสอบถามฐานข้อมูลและบันทึกผลลัพธ์ของแบบสอบถามเหล่านั้นไปยังฐานข้อมูลแยกต่างหากที่มีรสชาติ / ประเภทเดียวกัน สมมติว่าฉันมีเธรดคนงานจำนวนมากที่จัดการคิวรีฐานข้อมูลทั้งหมดที่ส่งไปยังคิว

#in a long running loop
try:
    query = queue.get()
    conn = connect_to_db(<main db>)
    curs = conn.cursor()
    try:
        curs.execute("<some query on user input that may fail even if sanitized">)
    except DBError:
        logconn = connect_to_db(<logging db>)
        logcurs = logconn.cursor()
        logcurs.execute("<update in DB log with record of failed query")
        logcurs.close()
        logconn.close()
    else:

        #we can't put this in main try block because an error connecting
        #to the logging DB would be indistinguishable from an error in 
        #the mainquery 

        #We can't put this after the whole try: except: finally: block
        #because then we don't know if the query was successful or not

        logconn = connect_to_db(<logging db>)
        logcurs = logconn.cursor()
        logcurs.execute("<update in DB log with record of successful query")
        logcurs.close()
        logconn.close()
        #do something in response to successful query
except DBError:
    #This DBError is because of a problem with the logging database, but 
    #we can't let that crash the whole thread over what might be a
    #temporary network glitch
finally:
    curs.close()
    conn.close()
    #other cleanup if necessary like telling the queue the task is finished

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


1

elseบล็อกมักจะสามารถอยู่เพื่อเสริมการทำงานที่เกิดขึ้นในทุกexceptบล็อก

try:
    test_consistency(valuable_data)
except Except1:
    inconsistency_type = 1
except Except2:
    inconsistency_type = 2
except:
    # Something else is wrong
    raise
else:
    inconsistency_type = 0

"""
Process each individual inconsistency down here instead of
inside the except blocks. Use 0 to mean no inconsistency.
"""

ในกรณีนี้inconsistency_typeมีการตั้งค่าในแต่ละบล็อกยกเว้นเพื่อให้พฤติกรรมที่สมบูรณ์ในกรณีที่ไม่มีข้อผิดพลาดelseมา

แน่นอนฉันกำลังอธิบายสิ่งนี้เป็นรูปแบบที่อาจปรากฏในรหัสของคุณสักวัน ในกรณีเฉพาะนี้คุณเพิ่งตั้งค่าinconsistency_typeเป็น 0 ก่อนถึงtryบล็อก


1

ที่นี่เป็นอีกที่ที่ฉันชอบใช้รูปแบบนี้:

 while data in items:
     try
        data = json.loads(data)
     except ValueError as e:
        log error
     else:
        # work on the `data`

1
คุณสามารถใช้continueแทน - รูปแบบ "แยกออกเร็ว" สิ่งนี้ช่วยให้คุณสามารถวางประโยค "else" และการเยื้องของมันทำให้โค้ดอ่านง่ายขึ้น
malthe

1

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

while True:
    try:
        r = random.random()
        some_operation_that_fails_for_specific_r(r)
    except Exception:
        continue
    else:
        break

แต่หากข้อยกเว้นสามารถคาดการณ์ได้คุณควรเลือกการตรวจสอบความถูกต้องล่วงหน้าเสมอยกเว้น อย่างไรก็ตามไม่สามารถคาดเดาได้ทุกอย่างดังนั้นรูปแบบรหัสนี้จึงมีอยู่


1
คุณสามารถทำได้ breakภายในtryที่สิ้นสุดซึ่งเป็นเครื่องดูด IMO elseและคุณไม่จำเป็นต้อง นอกจากนี้ไม่จำเป็นจริงๆคุณสามารถเพียงแค่continue pass
Dirbaio

1

ฉันพบว่าelseมีประโยชน์สำหรับการจัดการกับไฟล์ปรับแต่งที่อาจไม่ถูกต้อง:

try:
    value, unit = cfg['lock'].split()
except ValueError:
    msg = 'lock monitoring config must consist of two words separated by white space'
    self.log('warn', msg)
else:
     # get on with lock monitoring if config is ok

ข้อยกเว้นในการอ่านการกำหนดค่าlockปิดใช้งานการตรวจสอบการล็อกและ ValueErrors บันทึกข้อความเตือนที่เป็นประโยชน์


1

สมมติว่าตรรกะการเขียนโปรแกรมของคุณขึ้นอยู่กับว่าพจนานุกรมมีรายการที่มีคีย์ที่กำหนดหรือไม่ คุณสามารถทดสอบผลลัพธ์ของการdict.get(key)ใช้การif... else...สร้างหรือคุณสามารถทำ:

try:
    val = dic[key]
except KeyError:
    do_some_stuff()
else:
    do_some_stuff_with_val(val)

-1

ฉันจะเพิ่มกรณีการใช้งานอื่นที่ดูเหมือนตรงไปตรงมาเมื่อจัดการเซสชัน DB:

    # getting a DB connection 
    conn = db.engine.connect()

    # and binding to a DB session
    session = db.get_session(bind=conn)

    try:
        # we build the query to DB
        q = session.query(MyTable).filter(MyTable.col1 == 'query_val')

        # i.e retrieve one row
        data_set = q.one_or_none()

        # return results
        return [{'col1': data_set.col1, 'col2': data_set.col2, ...}]

    except:
        # here we make sure to rollback the transaction, 
        # handy when we update stuff into DB
        session.rollback()
        raise

    else:
        # when no errors then we can commit DB changes
        session.commit()

    finally:
        # and finally we can close the session
        session.close()

-17

else:บล็อกเป็นความสับสนและ (เกือบ) ไร้ประโยชน์ นอกจากนี้ยังเป็นส่วนหนึ่งของforและwhileงบ

ที่จริงแม้จะอยู่ในสถานะifที่else:สามารถถูกทำร้ายในรูปแบบที่น่ากลัวอย่างแท้จริงการสร้างข้อบกพร่องที่หายากมาก

พิจารณาสิ่งนี้.

   if a < 10:
       # condition stated explicitly
   elif a > 10 and b < 10:
       # condition confusing but at least explicit
   else:
       # Exactly what is true here?
       # Can be hard to reason out what condition is true

else:คิดรอบคอบเกี่ยวกับ เป็นปัญหาโดยทั่วไป หลีกเลี่ยงยกเว้นในสถานะ - ifและจากนั้นพิจารณาการจัดทำelseเงื่อนไขเพื่อให้ชัดเจน


6
ฉันจะไม่เห็นด้วยกับสิ่งนี้ ในบล็อก "if-elif" จะใช้ "else" เป็น "ค่าเริ่มต้น" ในบล็อก "case" ของภาษา C ขอแนะนำเสมอในการจัดการกรณี "เริ่มต้น" แม้ว่าคุณคิดว่าคุณได้ครอบคลุมทุกกรณีในเงื่อนไขต่างๆ
Josip

1
@Josip: ใช้เป็น "ค่าเริ่มต้น" อาจสร้างความสับสน ปัญหาคือการกำหนดเงื่อนไขที่ชัดเจนว่าเป็น "ค่าเริ่มต้น" นี้ เงื่อนไขเริ่มต้นที่กำหนดไว้ไม่ดีอาจเป็นสาเหตุของพฤติกรรมรถ อาจเป็นสาเหตุของความสับสน ควรมีการไตร่ตรองอย่างรอบคอบในทุกกรณีไม่เพียง แต่พยายามและในขณะที่ แต่ถ้าเป็นเช่นนั้น
S.Lott

5
รหัสข้างต้นเป็นนามธรรมโดยสมบูรณ์และไม่ได้ทำอะไรที่มีความหมายดังนั้นใช่ - ไม่น่าแปลกใจที่มันสับสน
julx

1
@ S.Lott "มันจะลดความบั๊ก" - และจุดของฉันคือว่านี้เป็นเท็จ ฉันคิดว่าเรามีความคิดเห็นที่แตกต่างอย่างแท้จริง โปรแกรมเมอร์ที่ไม่ดีมักจะหาวิธีในการเขียนโปรแกรมบั๊กกี้ เสมอ. โปรแกรมเมอร์ที่ดีมักแสวงหาแนวทางปฏิบัติที่ดีและสามารถเขียนโค้ดที่ดีได้ในภาษาใดก็ได้ การกำจัดสิ่งก่อสร้างที่มีประโยชน์เพียงแค่ให้พลังแก่โปรแกรมเมอร์ที่ดีน้อยลงในขณะที่ไม่ช่วยคนเลวโดยเฉพาะเพราะสิ่งเหล่านั้นสามารถประดิษฐ์วิธีที่ไม่ จำกัด จำนวนมากเพื่อกำจัดสิ่งต่าง ๆ
julx

5
พิจารณาและif x > 0: return "yes" if x <= 0: return "no"ตอนนี้มีคนเข้ามาและเปลี่ยนแปลงเงื่อนไขข้อหนึ่งเพื่อพูดx > 1แต่ลืมเปลี่ยนอีกข้อหนึ่ง วิธีการที่จะลดจำนวนข้อบกพร่องที่จะมุ่งมั่น if elseส่วนคำสั่งบางครั้งก็แยกกันหลายบรรทัด DRY เป็นแนวปฏิบัติที่ดีบ่อยกว่าไม่มาก (ขออภัยสำหรับการโพสต์สองครั้ง)
julx
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.