3

在 Python 中使用 class 作为特殊值是不是很难看?

考虑一下:

def find_result():
    result = None
    # do something to find the result, even recursing
    return result

r = find_result()
if r is None:
     raise Exception("we have no result")

如果我希望结果是数字或任何“正常”类型,这将非常有效。

但是如果有一个任意的数据结构,结果可以是从None另一个结构到另一个结构的任何东西呢?我在我的情况下所做的事情是这样的:

class NoResult:
    """i'm even less than `None`."""
    pass

def query(data, path):
    result = NoResult
    # traverse and recurse into the data structure
    return result

r = query()
if r is NoResult:
     raise Exception("our hands are empty")

行得通,但我无法摆脱我有点虐待这里的穷人的感觉,甚至可能潜伏着真正的危险。

这是真的吗?我在滥用课堂吗?或者只是我的算法很糟糕,如果它需要依赖这样的“特殊None”?

4

2 回答 2

5

它被称为哨兵,您可以为它使用任何独特的对象:

sentinel = object()

if r is sentinel:
    raise Exception(..)

在这里,我使用了一个简单的object()实例而不是自定义类。

自定义类确实有一个优势,那就是它可能更具自我记录性。如果您的 API必须将对象传递给 API 的用户(可以是代码),那么显式类会更好。对于只在 API 的黑匣子中使用,object()就可以了。

您可能需要考虑在您现在返回哨兵的地方引发异常。您总是可以再次捕获异常。

于 2013-10-03T12:52:03.717 回答
2

只是为了向 Martijn 建议添加另一种方法,就是使用异常机制让find_result首先抛出“无结果”异常,然后让调用者决定如何处理它。

def find_result():
    result = None
    if (...):
        raise NoResultException("details")
    return result

try:
    r = find_result()
except NoResultException:
     raise Exception("we have no result")
于 2013-10-03T12:59:53.787 回答