在Python中,我不时会看到以下代码块:

try:
   try_this(whatever)
except SomeException as exception:
   #Handle exception
else:
   return something

What is the reason for the try-except-else to exist?

我不喜欢这种编程,因为它使用异常来执行流控制.然而,如果它被包含在语言中,肯定有一个很好的理由,不是吗?

It is my understanding that exceptions are not errors,并且它们只能用于特殊情况(例如,我试图将文件写入磁盘,但没有更多空间,或者可能我没有权限),并且不能用于流控制.

通常情况下,我会将异常处理为:

something = some_default_value
try:
    something = try_this(whatever)
except SomeException as exception:
    #Handle exception
finally:
    return something

或者如果我真的不想在发生异常时返回任何内容,那么:

try:
    something = try_this(whatever)
    return something
except SomeException as exception:
    #Handle exception

推荐答案

"我不知道这是不是出于无知,但我不喜欢这样. 一种编程,因为它使用异常来执行流控制."

在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子句最常见的用法是为了美化(将异常结果和非异常结果在相同的缩进级别上对齐).这种使用通常是可选的,并非绝对必要.

Python相关问答推荐

从包含基本数据描述的文本字段中识别和检索特定字符序列

如何将 map 数组组合到pyspark中每列的单个 map 中

如何将uint 16表示为float 16

如何计算部分聚合数据的统计数据

使用matplotlib pcolormesh,如何停止从一行绘制的磁贴连接到上下行?

指示组内的rejected_time是否在creation_timestamp后5分钟内

如何从FDaGrid实例中删除某些函数?

Locust请求中的Python和参数

如何在msgraph.GraphServiceClient上进行身份验证?

pandas DataFrame GroupBy.diff函数的意外输出

我从带有langchain的mongoDB中的vector serch获得一个空数组

沿着数组中的轴计算真实条目

删除所有列值,但判断是否存在任何二元组

按列分区,按另一列排序

我们可以为Flask模型中的id字段主键设置默认uuid吗

在vscode上使用Python虚拟环境时((env))

isinstance()在使用dill.dump和dill.load后,对列表中包含的对象失败

使用Python从rotowire中抓取MLB每日阵容

基于Scipy插值法的三次样条系数

Gunicorn无法启动Flask应用,因为无法将应用解析为属性名或函数调用.'"'' "