在 false = 0、true = 1、unknown = 2 时存在与 None 问题相似的问题(unknown 实际上也不是 true,但如果你不小心,它会评估为 True)。
我想出了一个老生常谈的方法来获得至少接近你想要的东西,我想。它至少会为您提供一些将在 if/else 和其他布尔 eval 实例中以三元方式进行评估的东西。
class Yes(object):
def __nonzero__(self):
return True
class No(object):
def __nonzero__(self):
return False
class Unknown(object):
def __nonzero__(self):
raise ValueError('Unknown typed values do not evaluate to True/False. Try using Ternary.eval().')
class Ternary(object):
def __init__(self, yes, no, unknown):
setattr(self, yes, Yes())
setattr(self, no, No())
setattr(self, unknown, Unknown())
@staticmethod
def eval(value, unknown_eval):
if isinstance(value, Unknown):
return unknown_eval
return bool(value)
用法:
t = Ternary('yes', 'no', 'unknown')
# Do stuff to assign ternary value to x
if Ternary.eval(x, True):
print 'x is yes or unknown'
if Ternary.eval(x, False):
print 'x is yes only'
您可以制作 Yes、No 和 Unknown 伪单例,让您稍微改进 eval。当您知道您的值将是是或否时,您仍然可以进行简单的 if 检查,但是如果您尝试在 Unknown 上执行直接 bool()(即 if x),您会得到一个 TypeError。不过,这将使您的代码更加明确,因为每次检查三元类型的值时,您都必须在代码中定义您希望在该条件的上下文中如何处理未知,所以这将是一个加号.
编辑:
我想到了一个需要较少特殊处理但灵活性较低的替代方案。改成上面这样:
class Unknown(object):
def __init__(self, eval):
self._eval = eval
def __nonzero__(self):
return self._eval
class Ternary(object):
def __init__(self, yes, no, unknown, unknown_eval):
setattr(self, yes, Yes())
setattr(self, no, No())
setattr(self, unknown, Unknown(unknown_eval))
用法:
t1 = Ternary('yes', 'no', 'unknown', True)
t2 = Ternary('yes', 'no', 'unknown', False)
# Do stuff to assign ternary values to x1 and x2
if x1:
print 'x is yes or unknown'
if x2:
print 'x is yes only'
这样做的好处是允许 nonzero 像 Unknown 中的规范要求那样工作,但它的缺点是从实例化中固定 Unknown 的 eval 并且不再允许 Unknown 成为伪单例。