Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 长异常链的优雅替代品?_Python - Fatal编程技术网

Python 长异常链的优雅替代品?

Python 长异常链的优雅替代品?,python,Python,很多时候,我发现自己在写这样的东西: try: procedure_a() except WrongProcedureError: try: procedure_b() except WrongProcedureError: try: procedure_c() except WrongProcedureError: give_up() 这太可怕了。有没有一种更优雅的方式来实

很多时候,我发现自己在写这样的东西:

try:
    procedure_a()
except WrongProcedureError:
    try:
        procedure_b()
    except WrongProcedureError:
        try:
            procedure_c()
        except WrongProcedureError:
            give_up()

这太可怕了。有没有一种更优雅的方式来实现这种“尝试直到没有例外”的逻辑?这似乎是一种会出现很多的事情;我希望有一些我不知道的语言功能是专门为这件事设计的。

您可以使用
for/else
构造:

for proc in [procedure_a, procedure_b, procedure_c]:
    try:
        proc()
    except WrongProcedureError:
        continue
    else:
        break
else:
    give_up()

for
循环的
else
子句只有在控件自然地从for子句的底部脱落时才会触发。如果您
中断
(如果三个过程中的任何一个没有抛出异常,您都会这样做),它将不会触发。

循环过程。将循环包装到函数中。如果成功,则提前从函数返回:

def try_all():
    for procedure in [procedure_a, procedure_b, procedure_c]:
        try:
            procedure()
            return
        except WrongProcedureError:
            continue
    give_up()

事实上,你的方法没有错。它使用普通的语言特性,并将其信息表达得非常清楚

其他方法也可以,但它们的理解有些复杂,可能只有在您有很多(不仅仅是3个)函数需要检查时才更可取。在这种情况下,我实际上会制作一个函数来隐藏这种复杂性

import itertools
from contextlib import suppress

def call_functions(funcs, give_up_func):
    for func in itertools.chain(funcs, [give_up_func]):
        with suppress(WrongProcedureError):
            func()
            return  # only reached when func does not raise WrongProcedureError.
这假设
放弃函数
不会引发该异常,
suppress
需要python 3(我认为是3.4)


然而,当您实际需要时,代码中可能存在一些根本性的错误。这似乎是某种“回退”操作,可能应该使用子类或附加参数或策略/工厂来解决,而不是嵌套的
try
,除了
s.

循环。你在寻找循环。重复做同样的事情是循环的目的。我想知道这里的真实情况。。。如果你经常这样做,那么也许代码可以被重新构造成不需要这样做?在任何给定的情况下,对代码所做的事情进行推理看起来确实很棘手;在
try:
block中中断
而不是使用
else:
子句?@fferri当然可以!YMMV,但我喜欢
try/except/else
。即使是像“
break
”这样明显的代码,也可以明确地表明
break
不是我期望失败的代码。