有没有比“except:pass”更简洁的选择?

2024-06-17 14:56:48 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个函数,它按优先顺序返回几个组的随机成员。事情是这样的:

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"

但是,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"

但我发现这个更不可读,因为我从来没有理由在感觉到系统性错误之前使用pass

有没有一个更有效的模式,或者我应该学会接受pass

注意:我想避免任何嵌套,因为以后可能会添加其他类型。


编辑

感谢所有说pass很好的人-这让人放心!

也要感谢那些建议用返回值None替换异常的人。我可以看出这是一个多么有用的模式,但我认为在这种情况下这在语义上是错误的:函数被要求执行一个不可能的任务,因此它们应该引发一个异常。我更喜欢遵循random模块的行为(例如random.choice([]))。


Tags: or函数getreturniffoodefbar
3条回答

pass很好(有一个原因是用语言写的!-),但无通行证替代方案只需要更多的嵌套:

try: return get_random_foo()
except IndexError:
    try: return get_random_bar()
    except IndexError:
        raise IndexError "no foos, no bars"

Python的Zen(import this来自交互式解释器提示)说“扁平比嵌套好”,但是嵌套在语言中也是,当您决定(大概是被启发)您可以做得比智者koan更好时,您可以使用它!-)(比如,“如果你在路上遇到佛陀”…)。

我觉得有点奇怪,get_random_foo()在不将索引作为参数时引发索引器错误(但在上下文中可能更合理)。为什么不让get_random_foo()或包装器捕获错误并返回None呢?

def get_random_foo_wrapper():
    try:
        return get_random_foo()
    except IndexError:
        return None

def get_random_foo_or_bar():
    "I'd rather have a foo than a bar."

    return get_random_foo_wrapper() or get_random_bar_wrapper() or None

编辑:我应该提到,如果foo&bar是可能求值为False的对象(比如说0或“”),那么or比较将跳过那些不好的对象

我就是这样写的。很简单,也很有意义。我认为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"

相关问题 更多 >