"我不知道这是不是出于无知,但我不喜欢这样.
一种编程,因为它使用异常来执行流控制."
在Python世界中,使用异常进行流控制是常见和正常的.
即使是Python核心开发人员也使用异常进行流控制,并且这种风格在语言中有很大的影响(即迭代器协议使用StopIteration来表示循环终止).
此外,try-except样式用于防止"look-before-you-leap"个构造中的某些固有的竞争条件.例如,在使用os.path.exists时,测试结果中的信息可能已经过时.同样,Queue.full返回可能过时的信息.在这些情况下,try-except-else style将生成更可靠的代码.
"我的理解是,例外不是错误,它们应该只是
在其他一些语言中,这一规则反映了他们的文化规范,就像他们的图书馆所反映的那样."规则"还部分基于对这些语言的性能考虑.
Python的文化规范有些不同.在许多情况下,可以使用异常来控制流.此外,在Python中使用异常并不会像在某些编译语言中那样降低周围代码和调用代码的速度(例如,CPython已经在每个步骤中实现了异常判断代码,无论您是否实际使用异常).
换句话说,您对"异常是针对异常的"的理解在其他一些语言中是有意义的,但在Python中是没有意义的.
"但是,如果它包含在语言本身中,则必须有
这是很好的理由,不是吗?"
除了有助于避免竞争条件外,异常对于将错误处理拉到循环之外也非常有用.在解释语言中,这是一个必要的优化,而解释语言往往没有自动loop invariant code motion.
此外,在处理问题的能力与出现问题的地方相go 甚远的常见情况下,异常可以大大简化代码.例如,通常有顶级用户界面代码调用业务逻辑代码,而业务逻辑又调用低级 routine .低级 routine 中出现的情况(例如数据库访问中唯一密钥的重复记录)只能在顶级代码中处理(例如要求用户提供与现有密钥不冲突的新密钥).对这种控制流使用异常允许中级 routine 完全忽略这个问题,并与流控制的这一方面很好地解耦.
有一个nice blog post on the indispensibility of exceptions here.
Also, see this Stack Overflow answer: Are exceptions really for exceptional errors?
"除了其他原因,try 的原因是什么?"
else子句本身很有趣.它在没有例外的情况下,但在finally子句之前运行.这是它的主要目的.
如果没有else子句,在完成之前运行其他代码的唯一选项是将代码添加到try子句中的笨拙做法.这很笨拙,因为它有风险
在完成之前运行额外的无保护代码的用例并不经常出现.因此,不要期望在已发布的代码中看到很多示例.这有点罕见.
else子句的另一个用例是执行在没有异常发生时必须发生的操作,以及在处理异常时不发生的操作.例如:
recip = float('Inf')
try:
recip = 1 / f(x)
except ZeroDivisionError:
logging.info('Infinite result')
else:
logging.info('Finite result')
另一个例子发生在unittest Runner中:
try:
tests_run += 1
run_testcase(case)
except Exception:
tests_failed += 1
logging.exception('Failing test case: %r', case)
print('F', end='')
else:
logging.info('Successful test case: %r', case)
print('.', end='')
最后,try块中else子句最常见的用法是为了美化(将异常结果和非异常结果在相同的缩进级别上对齐).这种使用通常是可选的,并非绝对必要.