Ian*_*non 7 python coding-style exception-handling
我有一个函数,按优先顺序返回几个组的随机成员.它是这样的:
def get_random_foo_or_bar():
"I'd rather have a foo than a bar."
if there_are_foos():
return get_random_foo()
if there_are_bars():
return get_random_bar()
raise IndexError, "No foos, no bars"
Run Code Online (Sandbox Code Playgroud)
然而,首先要做的get_random_foo是验证是否有foos并且IndexError如果没有则提高,所以there_are_foos是多余的.此外,涉及数据库并使用单独的函数会产生并发问题.因此,我重写了这样的事情:
def get_random_foo_or_bar():
"Still prefer foos."
try:
return get_random_foo()
except IndexError:
pass
try:
return get_random_bar()
except IndexError:
pass
raise IndexError, "No foos, no bars"
Run Code Online (Sandbox Code Playgroud)
但我发现这个可读性要低得多,而且在我pass觉得错误之前我没有理由使用它.
是否有更整洁有效的模式,还是我应该学会接受pass?
注意:我想避免任何嵌套,因为以后可能会添加其他类型.
编辑
谢谢所有说这pass很好的人 - 这让人放心!
还要感谢那些建议用返回值替换异常的人None.我可以看到这是一个有用的模式,但我认为在这种情况下它在语义上是错误的:已经要求函数执行一个不可能完成的任务,因此它们应该引发异常.我更喜欢遵循random模块的行为(例如random.choice([])).
Joh*_*ica 13
这正是我写它的方式.这很简单,也很有道理.我认为这些pass陈述没有问题.
如果您想减少重复次数并且预计会添加未来类型,则可以将其转换为循环.然后你可以改变pass一个功能相当的continue语句,如果你的眼睛更令人愉悦:
for getter in (get_random_foo, get_random_bar):
try:
return getter()
except IndexError:
continue # Ignore the exception and try the next type.
raise IndexError, "No foos, no bars"
Run Code Online (Sandbox Code Playgroud)
小智 6
使用 try、 except、 pass 是可以接受的,但是有一种更简洁的方法可以使用contextlib.suppress()适用于 python 3.4+ 的方法来编写此代码。
from contextlib import suppress
def get_random_foo_or_bar():
"Still prefer foos."
with suppress(IndexError):
return get_random_foo()
with suppress(IndexError):
return get_random_bar()
raise IndexError("No foos, no bars")
Run Code Online (Sandbox Code Playgroud)