การใช้เจตนาของelseอนุประโยคทางเลือกของtryคำสั่งคืออะไร?
การใช้เจตนาของelseอนุประโยคทางเลือกของtryคำสั่งคืออะไร?
คำตอบ:
คำสั่งใน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
finallyบล็อกและIOErrorเกิดขึ้นไม่ได้ถูกจับที่นี่return, หรือcontinue break
                    มีเหตุผลสำคัญอย่างหนึ่งในการใช้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"
ใช้เพียงครั้งเดียว: ทดสอบโค้ดบางอย่างที่ควรเพิ่มข้อยกเว้น
try:
    this_should_raise_TypeError()
except TypeError:
    pass
except:
    assert False, "Raised the wrong exception type"
else:
    assert False, "Didn't raise any exception"
(รหัสนี้ควรจะถูกนำไปใช้ในการทดสอบทั่วไปมากขึ้นในทางปฏิบัติ)
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!
              ลองใช้ข้อยกเว้นที่ดีสำหรับการรวมรูปแบบ 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 ที่จะแจ้งให้ฉันทราบว่ากำลังถูกกลืนหายไป ถ้าฉันเขียนมันถูกต้อง แต่วิธีการล้างข้อมูลบางครั้งก็ถูกส่งผ่านประเภทผู้ใช้ที่มีแอตทริบิวต์ที่ผิดพลาด ขอให้โชคดีในการดีบักอันนั้น
ฉันพบว่ามีประโยชน์จริง ๆ เมื่อคุณล้างข้อมูลที่ต้องทำแม้ว่าจะมีข้อยกเว้น:
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()
              แม้ว่าคุณจะไม่สามารถคิดถึงการใช้งานได้ในตอนนี้ แต่คุณสามารถเดิมพันได้ว่าจะต้องมีการใช้งาน นี่คือตัวอย่างที่ไร้จินตนาการ:
ด้วย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บล็อกได้ แต่ต้องมีการตรวจจับยุ่งเหยิงหากกำหนดตัวแปรไว้
something = a[2]; print somethingการลอง: บล็อก
                    มีตัวอย่างที่ดีของการเป็นtry-elseในPEP 380 โดยพื้นฐานแล้วการจัดการข้อยกเว้นที่แตกต่างกันในส่วนต่างๆของอัลกอริทึม
มันเป็นแบบนี้:
try:
    do_init_stuff()
except:
    handle_init_suff_execption()
else:
    try:
        do_middle_stuff()
    except:
        handle_middle_stuff_exception()
สิ่งนี้ช่วยให้คุณสามารถเขียนรหัสการจัดการข้อยกเว้นใกล้กับข้อยกเว้นที่เกิดขึ้น
จากข้อผิดพลาดและข้อยกเว้น # การจัดการข้อยกเว้น - 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 ... ยกเว้นโดยไม่ได้ตั้งใจ
ดูที่การอ้างอิงของ Pythonดูเหมือนว่าelseจะถูกดำเนินการหลังจากที่tryไม่มีข้อยกเว้น ส่วนคำสั่งอื่นเป็นตัวเลือกจะดำเนินการถ้าและเมื่อการควบคุมไหลออกจากส่วนท้ายของข้อลอง 2ข้อยกเว้นในข้ออื่นไม่ได้รับการจัดการโดยข้อยกเว้นก่อนหน้านี้
ดำน้ำใน pythonมีตัวอย่างที่ถ้าฉันเข้าใจถูกต้องในtryบล็อกพวกเขาพยายามที่จะนำเข้าโมดูลเมื่อที่ล้มเหลวคุณจะได้รับข้อยกเว้นและผูกเริ่มต้น แต่เมื่อมันทำงานคุณมีตัวเลือกที่จะเข้าสู่elseบล็อกและผูกสิ่งที่จำเป็น (ดู ลิงค์สำหรับตัวอย่างและคำอธิบาย)
หากคุณพยายามที่จะทำงานในcatchบล็อกมันอาจทำให้เกิดข้อยกเว้นอื่น - ฉันคิดว่านั่นคือสิ่งที่elseบล็อกมีประโยชน์
tryบล็อก
                    แค่นั้นแหละ. บล็อก '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
ส่วนตัวผมชอบมันและใช้งานได้ตามความเหมาะสม มันจัดกลุ่มคำสั่ง
บางทีการใช้อาจเป็น:
#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()
บางทีนี่อาจจะนำคุณไปใช้เช่นกัน
ฉันได้พบ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
แน่นอนว่าถ้าคุณสามารถแยกแยะความแตกต่างระหว่างข้อยกเว้นที่อาจเกิดขึ้นได้คุณไม่จำเป็นต้องใช้สิ่งนี้ แต่ถ้ารหัสที่ตอบสนองกับส่วนที่ประสบความสำเร็จของรหัสนั้นอาจโยนข้อยกเว้นเดียวกับชิ้นส่วนที่ประสบความสำเร็จ ปล่อยให้ข้อยกเว้นที่สองเป็นไปได้หรือกลับไปสู่ความสำเร็จทันที (ซึ่งจะฆ่าเธรดในกรณีของฉัน) จากนั้นสิ่งนี้มีประโยชน์
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บล็อก
ที่นี่เป็นอีกที่ที่ฉันชอบใช้รูปแบบนี้:
 while data in items:
     try
        data = json.loads(data)
     except ValueError as e:
        log error
     else:
        # work on the `data`
              continueแทน - รูปแบบ "แยกออกเร็ว" สิ่งนี้ช่วยให้คุณสามารถวางประโยค "else" และการเยื้องของมันทำให้โค้ดอ่านง่ายขึ้น
                    หนึ่งในสถานการณ์การใช้งานที่ฉันนึกได้คือข้อยกเว้นที่คาดเดาไม่ได้ซึ่งสามารถหลีกเลี่ยงได้หากคุณลองอีกครั้ง ตัวอย่างเช่นเมื่อการดำเนินการในบล็อกลองเกี่ยวข้องกับตัวเลขสุ่ม:
while True:
    try:
        r = random.random()
        some_operation_that_fails_for_specific_r(r)
    except Exception:
        continue
    else:
        break
แต่หากข้อยกเว้นสามารถคาดการณ์ได้คุณควรเลือกการตรวจสอบความถูกต้องล่วงหน้าเสมอยกเว้น อย่างไรก็ตามไม่สามารถคาดเดาได้ทุกอย่างดังนั้นรูปแบบรหัสนี้จึงมีอยู่
breakภายในtryที่สิ้นสุดซึ่งเป็นเครื่องดูด IMO elseและคุณไม่จำเป็นต้อง นอกจากนี้ไม่จำเป็นจริงๆคุณสามารถเพียงแค่continue pass
                    ฉันพบว่า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 บันทึกข้อความเตือนที่เป็นประโยชน์
สมมติว่าตรรกะการเขียนโปรแกรมของคุณขึ้นอยู่กับว่าพจนานุกรมมีรายการที่มีคีย์ที่กำหนดหรือไม่ คุณสามารถทดสอบผลลัพธ์ของการdict.get(key)ใช้การif... else...สร้างหรือคุณสามารถทำ:
try:
    val = dic[key]
except KeyError:
    do_some_stuff()
else:
    do_some_stuff_with_val(val)
              ฉันจะเพิ่มกรณีการใช้งานอื่นที่ดูเหมือนตรงไปตรงมาเมื่อจัดการเซสชัน 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()
              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เงื่อนไขเพื่อให้ชัดเจน
if x > 0: return "yes" if x <= 0: return "no"ตอนนี้มีคนเข้ามาและเปลี่ยนแปลงเงื่อนไขข้อหนึ่งเพื่อพูดx > 1แต่ลืมเปลี่ยนอีกข้อหนึ่ง วิธีการที่จะลดจำนวนข้อบกพร่องที่จะมุ่งมั่น if elseส่วนคำสั่งบางครั้งก็แยกกันหลายบรรทัด DRY เป็นแนวปฏิบัติที่ดีบ่อยกว่าไม่มาก (ขออภัยสำหรับการโพสต์สองครั้ง)