如何提高嵌套的try-except-else子句中的代码清晰度? [英] How to improve code clarity in nested try-except-else clauses?
问题描述
有时候,我可以尝试一堆不同的事情,例如尝试完成一项任务。 G。如果需要获取记录,我可以先尝试查找记录,如果失败,则可以创建丢失的记录,如果失败了,也可以使用磁带。
Sometimes I have a cascade of different things I can try to accomplish a task, e. g. If I need to get a record I can first try to find the record, and if this fails, I can create the missing record, and if this also fails, I can use a tape instead.
失败是通过引发我的代码需要捕获的异常来表示的。
Failing is represented by throwing an exception my code needs to catch.
在Python中,它看起来像这样:
In Python this looks something like this:
try:
record = find_record()
except NoSuchRecord:
try:
record = create_record()
except CreateFailed:
record = tape
此已经具有堆积压痕的缺点。如果我有五个选择,那么这段代码看起来会不好看。
This already has the disadvantage of piling-up indentations. If I have five options, this code won't look good.
但是当还有 else $时,我发现它甚至更成问题。
try
-的c $ c>子句,除了
子句除外:
But I find it even more problematic when there are also else
clauses to the try
-except
clauses:
try:
record = find_record()
except NoSuchRecord:
try:
record = create_record()
except CreateFailed:
record = tape
logger.info("Using a tape now")
else:
logger.info("Created a new record")
else:
logger.info("Record found")
find_record()
和相应的 Record found
消息距离尽可能远,这使得很难阅读代码。 (仅将 else
子句的代码直接移到 try
子句中是一种选择, except
语句中捕获的异常之一,因此这不是一般解决方案。)
The find_record()
and the corresponding Record found
message are as far apart as possible which makes it hard to read code. (Moving the code of the else
clause directly into the try
clause is only an option if this code is definitely not raising one of the exceptions caught in the except
statement, so this is no general solution.)
同样,这很丑陋每增加一层嵌套,情况就会变得更糟。
Again, this ugliness gets worse with each added level of nesting.
有没有更好的方法将其放入Python代码
Is there a nicer way to put this into Python code
- 不更改行为,
- 同时保持
try
和except <一个主题的/ code>子句紧密结合在一起和/或
- 也许还避免了堆积的嵌套和缩进?
- without changing the behavior and
- while keeping the
try
and theexcept
clauses of one topic closely together and/or - maybe also avoiding the piling-up nesting and indenting?
推荐答案
您可以使用 for
循环依次尝试变体:
You can use a for
loop to successively try variants:
for task, error in ((find_record, NoSuchRecord), (create_record, CreateFailed)):
try:
result = task()
except error:
continue
else:
break
else:
# for..else is only entered if there was no break
result = tape
$时输入b
$ b
如果需要 else
子句,可以将其作为单独的函数提供:
If you need an else
clause, you can provide it as a separate function:
for task, error, success in (
(find_record, NoSuchRecord, lambda: logger.info("Record found")),
(create_record, CreateFailed, lambda: logger.info("Created a new record"))
):
try:
result = task()
except error:
continue
else:
success()
break
else:
result = tape
logger.info("Using a tape now")
请注意,默认情况下 tape
是 not 部分变体-这是因为它没有失败条件。如果应使用变体执行,则可以将其添加为(lambda:磁带,(),lambda:无)
。
Take note that the default case tape
is not part of the variants - this is because it has no failure condition. If it should execute with the variants, it can be added as (lambda: tape, (), lambda: None)
.
您可以将所有这些放到函数中以供重用:
You can put this all into a function for reuse:
def try_all(*cases):
for task, error, success in cases:
try:
result = task()
except error:
continue
else:
success()
return result
try_all(
(find_record, NoSuchRecord, lambda: logger.info("Record found")),
(create_record, CreateFailed, lambda: logger.info("Created a new record")),
(lambda: tape, (), lambda: logger.info("Using a tape now")),
)
如果元组似乎难以阅读,则 NamedTuple
可以用来命名元素。可以将其与普通元组混合使用:
In case the tuples seem difficult to read, a NamedTuple
can be used to name the elements. This can be mixed with plain tuples:
from typing import NamedTuple, Callable, Union, Tuple
from functools import partial
class Case(NamedTuple):
task: Callable
error: Union[BaseException, Tuple[BaseException, ...]]
success: Callable
try_all(
Case(
task=find_record,
error=NoSuchRecord,
success=partial(logger.info, "Record found")),
(
create_record, CreateFailed,
partial(logger.info, "Created a new record")),
Case(
task=lambda: tape,
error=(),
success=partial(logger.info, "Using a tape now")),
)
这篇关于如何提高嵌套的try-except-else子句中的代码清晰度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!