การใช้เจตนาของ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
ช่วยให้คุณสามารถตรวจสอบให้แน่ใจfinally
else
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
และสามารถหยุดการไหลของการควบคุมbreak
else
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 เป็นแนวปฏิบัติที่ดีบ่อยกว่าไม่มาก (ขออภัยสำหรับการโพสต์สองครั้ง)