布尔值有两个可能的值.是否存在具有三个可能值的类型?

2022-01-19 00:00:00 python logic boolean

问题描述

可能重复:
在 Python 中实现枚举"的最佳方法是什么?

我正在编写一个函数,理想情况下,我希望返回以下三种状态之一:是"、否"和不知道".

I’m writing a function that, ideally, I’d like to return one of three states: "yes", "no", and "don’t know".

  1. 是否有任何编程语言的类型具有三个且只有三个状态?类似于布尔值,但具有三种状态而不是两种状态?

  1. Do any programming languages have a type that has three, and only three states? Like a boolean, but with three states instead of two?

在没有这种类型的语言(如 Python)中,表示这种类型的最佳类型是什么?

In languages that don’t have such a type (like Python), what’s the best type to represent this?

目前我想我会选择一个整数(0 表示否",1 表示不知道",2 表示是"),但也许有更好的方法?整数似乎有点幻数".

Currently I think I’ll go with an integer (0 for "no", 1 for "don’t know" and 2 for "yes"), but maybe there’s a better way? Integers seem a bit "magic number".

我可以返回 TrueFalseNone,但因为 None 会评估为 False 在大多数比较上下文中,错误似乎有点成熟.

I could return True, False or None, but as None would evaluate to False in most comparison contexts it seems a bit ripe for errors.


解决方案

在 Python 中,我会使用包含这三个值之一的包装器对象来做到这一点;我会使用 TrueFalseNone.由于具有三个可能值的类布尔对象的隐含真实性值是有问题的,我们将通过完全禁止来解决这个问题(在__nonzero__()中引发异常,或在 Python 3 中,__bool__()),因此要求始终使用 in== 显式进行比较!=.我们将实现相等作为标识,以便仅匹配特定的单例值 TrueFalseNone.

In Python I'd do that with a wrapper object that holds one of those three values; I'd use True, False, and None. Since the implicit truthiness value of a Boolean-like object with three possible values is problematic, we'll solve that by disallowing that entirely (raising an exception in __nonzero__(), or in Python 3, __bool__()), thus requiring that comparisons always be done explicitly, using in, ==, or !=. We'll implement equality as identity so that only the specific singleton values True, False, and None are matched.

class Tristate(object):

    def __init__(self, value=None):
       if any(value is v for v in (True, False, None)):
          self.value = value
       else:
           raise ValueError("Tristate value must be True, False, or None")

    def __eq__(self, other):
       return (self.value is other.value if isinstance(other, Tristate)
               else self.value is other)

    def __ne__(self, other):
       return not self == other

    def __nonzero__(self):   # Python 3: __bool__()
       raise TypeError("Tristate object may not be used as a Boolean")

    def __str__(self):
        return str(self.value)

    def __repr__(self):
        return "Tristate(%s)" % self.value

用法:

t = Tristate(True)
t == True           # True
t != False          # True
t in (True, False)  # True
bool(t)             # Exception!
if t: print "woo"   # Exception!

使用 Tristate 对象时,您必须明确指定要匹配的值,即 foo == True 或 bar != None.您也可以执行 foo in (False, None) 来匹配多个值(当然 in 两个值与 != 相同单个值).如果您希望能够对这些对象执行其他逻辑操作,您可以将它们实现为方法,或者可能通过覆盖某些运算符(但遗憾的是,逻辑 notandor 不可覆盖,尽管有 建议添加).

When using Tristate objects, you must explicitly specify which values to match, i.e. foo == True or bar != None. You can also do foo in (False, None) to match multiple values (though of course in two values is the same as != with a single value). If there are other logic operations you wish to be able to perform with these objects, you could implement these as methods, or possibly by overriding certain operators (sadly, however, logical not, and, and or are not overrideable, though there's a proposal to add that).

另请注意,您不能在 Python 中覆盖 id(),例如Tristate(None) is None is False;这两个对象实际上是不同的.由于好的 Python 风格是在与单例比较时使用 is,这是不幸的,但也是不可避免的.

Also note that you can't override id() in Python, so e.g. Tristate(None) is None is False; the two objects are in fact different. Since good Python style is to use is when comparing against singletons, this is unfortunate, but unavoidable.

编辑 4/27/16:添加了将一个 Tristate 对象与另一个对象进行比较的支持.

Edit 4/27/16: Added support for comparing one Tristate object to another.

相关文章