gpt4 book ai didi

python - 如何提高嵌套 try-except-else 子句中的代码清晰度?

转载 作者:太空宇宙 更新时间:2023-11-03 12:43:17 25 4
gpt4 key购买 nike

有时我会尝试一系列不同的事情来完成一项任务,例如。 G。如果我需要获取记录,我可以先尝试找到该记录,如果找不到,我可以创建丢失的记录,如果这也失败,我可以使用磁带代替。

失败表示为抛出我的代码需要捕获的异常。

在 Python 中,这看起来像这样:

try:
record = find_record()
except NoSuchRecord:
try:
record = create_record()
except CreateFailed:
record = tape

这已经具有堆积压痕的缺点。如果我有五个选项,此代码将不会好看。

但是当 try-except 子句也有 else 子句时,我发现问题更大:

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< 中捕获的异常之一 语句,所以这不是通用的解决方案。)

同样,每增加一层嵌套,这种丑陋就会变得更糟。

有没有更好的方法将其放入 Python 代码中

  1. 不改变行为和
  2. 同时将一个主题的 tryexcept 子句紧密地放在一起和/或
  3. 也许还能避免堆积嵌套和缩进?

最佳答案

您可以使用 for 循环来连续尝试变体:

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

如果您需要 else 子句,可以将其作为单独的函数提供:

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 不是变体的一部分 - 这是因为它没有失败条件。如果它应该与变体一起执行,它可以添加为 (lambda: tape, (), lambda: None)


您可以将这些全部放入一个函数中以供重用:

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 来命名元素。这可以与普通元组混合:

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")),
)

关于python - 如何提高嵌套 try-except-else 子句中的代码清晰度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57974694/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com