== What the differences are between Python _bool_s and _int_s I mentioned in [[the previous entry EqualityDictSurprise]] that Python's _bool_ class is actually a subclass of _int_ (and the _bool_ docstring will tell you this if you bother to read it with _help()_ before, say, diving into the CPython source code like a [[system programmer ../sysadmin/SystemProgrammerDanger]]). Since I was just looking at this, I might as well write down the low-level differences between _int_s and _bool_s. Bools have: * a custom ((__repr__)) that reports _True_ or _False_ instead of the numeric value; this is also used as the custom ((__str__)) for _bool_. (The code is careful to _intern_ these strings so that no matter how many times you _repr()_ or _str()_ a boolean, only one copy of the literal 'True' or 'False' string will exist.) * a ((__new__)) that returns either the global _True_ object or the global _False_ object depending on the truth value of what it's given. * custom functions for _&_, _|_, and _^_ that implement boolean algebra instead of the standard bitwise operations if both arguments are either _True_ or _False_. Note that eg '_True & 1_' results in a bitwise operation and an _int_ object, even though _1_ is [[strongly equal EqualityDictSurprise]] to _True_. That's it. I'm not quite sure how _bool_ blocks being subclassed and I'm not curious enough right now to work it out. \\ Update: see the comments for the explanation. The global _True_ and _False_ objects are of course distinct from what is in effect the global _0_ and _1_ objects that are [[all but certain ObjectIdentityGotcha]] to exist. This means that their _id()_ is different (at least in CPython), since the _id()_ is the memory address of their C-level object _struct_. (In modern versions of both CPython 2 and CPython 3 it turns out that global _0_ and _1_ objects are guaranteed to exist, because 'small integers' between -5 and 257 are actually preallocated as the interpreter is initializing itself.)