Python 使用类作为特殊值?
在Python中使用类作为特殊值是不是很难看 考虑这一点:Python 使用类作为特殊值?,python,class,Python,Class,在Python中使用类作为特殊值是不是很难看 考虑这一点: 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") 如果我希望结果是数字或任何“正常”类型,那么这种方法非常有效 但是,如
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")
这是可行的,但我无法摆脱这样一种感觉:我有点虐待这里的贫困阶层,甚至可能有一个真正的危险潜伏在里面
这是真的吗?我是在辱骂学生吗?或者,如果我的算法需要依赖像这样的“特殊
无”,那么它就很糟糕?它被称为哨兵,你可以为它使用任何独特的对象:
sentinel = object()
if r is sentinel:
raise Exception(..)
这里我使用了一个简单的object()
实例,而不是自定义类
自定义类的优点是它可能更具有自文档性;如果您的API必须将对象传递给API的用户(可以是代码),那么显式类更好。只要在API的黑盒中使用,object()
就可以了
<>你可能想考虑在你现在返回哨兵点的时候提高异常。您总是可以再次捕获异常。只是为了给Martijn的建议添加另一种方法,就是使用异常机制让查找结果
首先抛出一个“无结果”异常,然后让调用方决定如何处理它
def find_result():
result = None
if (...):
raise NoResultException("details")
return result
try:
r = find_result()
except NoResultException:
raise Exception("we have no result")
为什么不在find\u result
中引发异常,而不是返回任何内容?引发异常的整个想法是提供一种与识别特殊返回值无关的替代错误检测机制。@chepner我这样做是因为我需要更深入地递归,而且我从来不知道在返回顶部调用之前我想停止搜索。现在我想起来了,也许通过适当的异常处理,它会更好…@AloisMahdal:是的;我看得出这是令人困惑的。稍微修改了一下句子。我刚刚使用了我的旧代码,发现了直接使用该类的另一个优点(即既不是它的实例,也不是泛型对象):当您打印它时,它是mymodule.NoResult
,而不是
(Python 2.7)。它是完全免费的(不需要\uu str\uu
s,只需classx:pass
)而且可读性更高,特别是如果您想使用多个哨兵。因此,即使您不打算打印它,它仍然有利于调试,并且万一它真的溜出去了,至少它可以将用户/您发送到正确的位置。这就是我提到的“自我记录”部分。:-)使用result=NoResult()
和'if-isinstance('r',NoResult')不是更好吗?也就是说,使用类的一个实例而不是类本身作为哨兵。@hpaulj:这有什么好处NoResult
是一个单例,这就是您所需要的。没有可跟踪的状态。