Possible Duplicate:
What's the best way to implement an 'enum' in Python?
I’m writing a function that, ideally, I’d like to return one of three states: “yes”, “no”, and “don’t know”.
Do any programming languages have a type that has three, and only three states? Like a boolean, but with three states instead of two?
In languages that don’t have such a type (like Python), what’s the best type to represent this?
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”.
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.
A variable of the primitive data type boolean can have two values: true and false (Boolean literals). or off. Boolean expressions use relational and logical operators. The result of a Boolean expression is either true or false.
It was interesting to read that the PostgreSQL boolean (alias “bool”) data type is actually Trinary not Binary and therefore has three possible states: TRUE, FALSE, and “unknown” (represented by a NULL). This is evidently the standard SQL three-valued logic system (also called Trinary, Ternary, Trivalent, 3VL, etc.
A Boolean variable has only two possible values: true or false. It is common to use Booleans with control statements to determine the flow of a program. In this example, when the boolean value "x" is true, vertical black lines are drawn and when the boolean value "x" is false, horizontal gray lines are drawn.
There are just two values of type bool: true and false. They are used as the values of expressions that have yes-or-no answers. The following table shows some operators that yield boolean results and some operations on boolean values.
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
Usage:
t = Tristate(True) t == True # True t != False # True t in (True, False) # True bool(t) # Exception! if t: print "woo" # Exception!
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).
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.
Edit 4/27/16: Added support for comparing one Tristate
object to another.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With