是否有一个更简洁的替代`except:pass`?

时间:2010-09-16 02:28:46

标签: python exception-handling coding-style

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

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([]))。

8 个答案:

答案 0 :(得分: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"

答案 1 :(得分:2)

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)说“flat比嵌套更好”,但是嵌套在语言中也是 ,供你在决定时使用(推测)被开悟了,你可以做得比那更明智的公主更好! - )(如同,“如果你在路上遇见佛陀......”)。

答案 2 :(得分:2)

get_random_foo()当它没有将索引作为参数(但在上下文中可能更有意义)时,get_random_foo()引发了一个IndexError,这看起来有点奇怪。为什么不让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 或包装器捕获错误并返回None?

or

编辑:我应该提一下,如果foo& bar是可以评估为False(0或'')的对象,然后{{1}}比较将跳过它们,这是不好的

答案 3 :(得分:1)

如果只是那两个,可能总是......

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

如果它超过两个,你所写的内容似乎完全可以接受。

答案 4 :(得分:1)

除try以外,可以使用try,但是有一种更干净的方法可以使用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")

答案 5 :(得分:0)

根据Peter Gibson的建议,您可以创建一个吞噬给定异常的通用包装函数。然后你可以编写一个函数,返回这样的通用包装器,用于提供的异常。或者,对于提供的列表例外情况。

def maketrap(*exceptions):
    def trap(func, *args, **kwargs):
        try:
            return func(*args, **kwargs)
        except exceptions:
            return None
    return trap

def get_random_foo_or_bar():
    mytrap = maketrap(IndexError)
    return mytrap(get_random_foo) or mytrap(get_random_bar) or None

答案 6 :(得分:0)

如果你真的不需要异常消息(只是类型):

def get_random_foo_or_bar():
    try:
        return get_random_foo()
    except IndexError:
        return get_random_bar()    # if failing at this point,
                                   # the whole function will raise IndexError

答案 7 :(得分:0)

如果它无法成功,get_random_foo / bar()是否需要引发IndexError?

如果他们返回None,你可以这样做:

def get_random_foo_or_bar():
    return get_random_foo() or get_random_bar()
相关问题