[英]Nesting try-except blocks leads to overly indented code
我在编写 Python 代码时遇到了一个相当哲学的问题。 通常,使用尽可能多的try-except-else
块来处理所有可预期的情况被认为是一种很好的风格。 但我发现这种方法有时会导致不必要的多级缩进,这使得很难将行数保持在 80 以下,并暗示代码中不存在层次结构。 我觉得我缺少某种“GOTO”语句或类似的跳转来应对这个问题。 因此,我想知道我是否缺少一些编码风格、Python 语句或模式来改进我的 Python 代码。
我举一个更具体的例子。 让我们认为我正在定义一个函数,并且我在一个循环中,在那里各种事情可能会出错。 每件事都足以使循环中的其余代码可跳过,我通常以类似于以下方式continue
跳过这些代码:
def mu_func()
failed = False
for i in range(100):
try:
pass
# we try something that might raise an exception
except:
print("something went wrong by reason #1")
failed = True
continue
try:
pass
# we try something that might raise an exception
except:
print("something went wrong by reason #2")
failed = True
continue
try:
pass
# we try something that might raise an exception
except:
print("something went wrong by reason #3")
failed = True
# some cleanup code at the end of the function
# that depends on the errors raised
return failed
这里要注意的重要一点是,由于我们处于循环中,如果引发任何异常, continue
语句使我不必使用else
语句跳过其余代码。 因此,缩进级别不会继续增长。 另请注意,我不能只是退出异常处理,因为我需要在从函数返回之前进行一些清理。
现在注意当我们不在循环中时会发生什么:
def mu_func()
failed = False
try:
pass
# we try something that might raise an exception
except:
print("something went wrong by reason #1")
failed = True
else:
try:
pass
# we try something that might raise an exception
except:
print("something went wrong by reason #2")
failed = True
else:
try:
pass
# we try something that might raise an exception
except:
print("something went wrong by reason #3")
failed = True
# some cleanup code at the end of the function
# that depends on the errors raised
return failed
看到不同? 如果想在引发任何异常后跳过其余代码,我必须将下面的所有内容放入else
语句中,从那时起,它会略微增加缩进级别。 这不仅会导致难以将行数保持在 80 个字符以下的烦人代码。 最糟糕的是,这些嵌套的try-except-else
块暗示了代码中的某种层次结构,这是人为的。 所有例外都同等重要。 在第一个示例中可以很容易地理解这一点,其中可以很好地交换try-except
块的顺序,而无需触及缩进且不影响功能。
是否有 Python 语句或模式允许我在处理异常后跳过其余代码,从而使我不必添加越来越多的缩进级别? 我是否误用了else
语句? 我很想把所有东西都放在一个简单的 1 次迭代循环中,这样我就可以访问continue
语句来执行跳转到我遗漏的块语句的末尾。
一种方法可能是用try-except
块包装 for 循环:
def mu_func():
try:
for i in range(100):
# we try something that might raise an exception
action_1()
print("action #1 succeeds")
action_2()
print("action #2 succeeds")
action_3()
print("action #3 succeeds")
except:
print("something went wrong!")
failed = True
else:
failed = False
return failed
如果你的 for 循环中有其他逻辑,我建议只包装可能引发异常的逻辑:
def mu_func():
for i in range(100):
try:
# we try something that might raise an exception
action_1()
print("action #1 succeeds")
action_2()
print("action #2 succeeds")
action_3()
print("action #3 succeeds")
except:
print("something went wrong!")
failed = True
break
# here we might do other stuff in the loop
...
else:
failed = False
return failed
怎么用:
def mu_func()
failed = False
try:
pass
# we try something that might raise an exception
except ExceptionClass1():
print("something went wrong by reason #1")
failed = True
except ExceptionClass2():
print("something went wrong by reason #2")
failed = True
except ExceptionClass3():
print("something went wrong by reason #3")
failed = True
except ExceptionClass4():
print("something went wrong by reason #4")
failed = True
return failed
我找到了 2 个解决问题的方法。 我会将它们张贴在这里以激发进一步的讨论或在我的情况下帮助其他人。 不过,我不会将此标记为答案,因为我发现它们更像是一种解决方法而不是正确的解决方案。 它们在某种程度上是基于这个问题的答案(我认为它接受的答案不能解决问题)。
使用虚拟循环的解决方案
这里的想法是伪造一个循环来访问允许您跳转到函数末尾的continue
语句。
def mu_func()
failed = False
for _ in range(1):
try:
pass
# we try something that might raise an exception
except Exception1:
print("something went wrong by reason #1")
failed = True
continue
try:
pass
# we try something that might raise an exception
except Exception2:
print("something went wrong by reason #2")
failed = True
continue
try:
pass
# we try something that might raise an exception
except Exception3:
print("something went wrong by reason #3")
failed = True
# some cleanup code at the end of the function
# that must be executed before leaving
return failed
这个解决方案有效,但它非常丑陋,因为以一种创造性的方式使用 for 循环,这显然不是它的设计目的。
使用2级异常处理的解决方案
这里的想法是定义和使用通用异常,并使用它来转换异常类型以表示出现问题(但它已经被处理),然后基本上将执行流程发送到最后。
class MyException(Exception):
pass
def mu_func()
failed = False
try:
try:
pass
# we try something that might raise an exception
except Exception1:
print("something went wrong by reason #1")
raise MyException
try:
pass
# we try something that might raise an exception
except Exception2:
print("something went wrong by reason #2")
raise MyException
try:
pass
# we try something that might raise an exception
except Exception3:
print("something went wrong by reason #3")
raise MyException
except MyException:
failed = True
# some cleanup code at the end of the function
# that depends on the errors raised
return failed
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.