语句的可选else
子句的预期用途是try
什么?
语句的可选else
子句的预期用途是try
什么?
Answers:
else
如果执行不符合try
-如果没有例外,则执行块中的语句。老实说,我从来没有发现需要。
但是,“ 处理异常”指出:
使用else子句比向try子句添加其他代码更好,因为它避免了意外捕获try ... except语句保护的代码未引发的异常。
所以,如果你有一个方法可以,例如,抛出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”的东西。
Python try-else
else
try语句的optional 子句的预期用途是什么?
如果没有预期处理异常的情况,则预期的用途是为更多代码运行提供上下文。
此上下文避免了意外处理您未预期到的错误。
但重要的是要了解导致else子句来运行的精确条件,因为return
,continue
和break
可中断的控制流else
。
该else
声明是否有运行没有异常,如果不是被打断return
,continue
或break
声明。
可选的
else
,如果条款被执行,并且当控制切断端流动的的try
条款。*
(加粗体。)脚注如下:
*目前,控制“落端流动”除了在异常或一个的执行的情况下
return
,continue
或break
语句。
它确实需要至少一个前面的except子句(请参阅语法)。因此,它实际上不是“ try-else”,而是“ try-except-else(-finally)”,else
(和finally
)是可选的。
在Python指南预期的使用详解:
try ... except语句具有可选的else子句,该子句在存在时必须遵循所有except子句。这对于try子句未引发异常的必须执行的代码很有用。例如:
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()
使用else子句比向try子句添加其他代码更好,因为它避免了意外捕获try ... except语句保护的代码未引发的异常。
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!
Try-except-else非常适合将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被吞噬了。更糟糕的是,如果我正确编写了该方法,但是偶尔会向该传递给具有错误名称属性的用户类型的清理方法,导致该方法在中途无声地失败并且未关闭文件?祝您调试好运。
即使您现在无法想到它的用途,您也可以打赌一定有它的用途。这是一个难以想象的示例:
与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:块内部有什么问题?
该
try ... except
语句有一个可选else
子句,当存在时,该子句必须遵循所有除子句之外的子句。这对于try子句未引发异常的必须执行的代码很有用。例如: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()
使用else子句比向try子句添加其他代码更好,因为它避免了意外捕获try ... except语句保护的代码未引发的异常。
查看Python参考,似乎else
是在try
没有异常的情况下执行的。当控制从try子句的末尾流出时,将执行可选的else子句。2 else子句中的异常不由前面的except子句处理。
深入研究python有一个例子,如果我理解正确,try
他们会在块中尝试导入模块,当该模块失败时,您将获得异常并绑定默认值,但是当它起作用时,您可以选择进入else
块并绑定所需的内容(请参阅示例和说明的链接)。
如果您尝试在代码catch
块中进行工作,则可能会引发另一个异常-我想这就是代码else
块派上用场的地方。
try
块。
而已。try-except子句的'else'块存在于(仅当)tryed操作成功时运行的代码。它可以被使用,也可以被滥用。
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
在每个except块中都设置,以便在中的无错误情况下补充行为else
。
当然,我将其描述为一种模式,有一天可能会在您自己的代码中出现。在这种情况下,无论如何您只需将其设置inconsistency_type
为0 try
。
我可以想到的一种使用场景是不可预测的异常,如果再次尝试可以避免这种异常。例如,当try块中的操作涉及随机数时:
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
。
我将添加另一个在处理数据库会话时似乎很简单的用例:
# 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
and 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
-statement中,否则应避免使用它,甚至还要考虑记录-condition else
以使其明确。
if x > 0: return "yes"
和if x <= 0: return "no"
。现在,一个人来改变一个要说的条件,x > 1
却忘记改变另一个条件。如何减少将要提交的错误数量。if else
子句有时相隔很多行。实际上,DRY是一种很好的做法,通常很多时候。(重复发帖,抱歉)。