PEP: 285 Title: Adding a bool type Version: $Revision$ Last-Modified: $Date$ Author: guido@python.org (Guido van Rossum) Status: Draft Type: Standards Track Created: 8-Mar-2002 Python-Version: 2.3 Post-History: 8-Mar-2002 Abstract This PEP proposes the introduction of a new built-in type, bool, with two constants, False and True. The bool type would be a straightforward subtype (in C) of the int type, and the values False and True would behave like 0 and 1 in most respects (for example, False==0 and True==1 would be true) except repr() and str(). All built-in operations that conceptually return a Boolean result will be changed to return False or True instead of 0 or 1; for example, comparisons and the "not" operator. Rationale Most languages eventually grow a Boolean type; even C99 has one. Many programmers apparently feel the need for a Boolean type; most Python documentation contains a bit of an apology for the absence of a Boolean type. I've seen lots of module that defined constants "False=0" and "True=1" (or similar) at the top and used those. The problem with this is that everybody does it differently. For example, should you use "FALSE", "false", "False", "F" or even "f"? And should false be the value zero or None, or perhaps a truth value of a different type that will print as "true" or "false"? Adding a standard bool type to the language resolves those issues. Some external libraries (like databases and RPC packages) need to be able to distinguish between Boolean and integral values, and while it's usually possible to create a solution, it would be easier if the language offered a standard Boolean type. And here's an argument derived from teaching Python. When showing people comparison operators etc. in the interactive shell, I think this is a bit ugly: >>> a = 13 >>> b = 12 >>> a > b 1 >>> If this was: >>> a > b True >>> it would require one millisecond less thinking each time a 0 or 1 was printed. There's also the issue (which I've seen puzzling even experienced Pythonistas who had been away from the language for a while) that if you see: >>> cmp(a, b) 1 >>> cmp(a, a) 0 >>> you might be tempted to believe that cmp() also returned a truth value. If ints are not (normally) used for Booleans results, this would stand out much more clearly as something completely different. Specification The following Python code specifies most of the properties of the new type: class bool(int): def __new__(cls, val=0): # This constructor doesn't return a new instance; # it returns an existing instance if val: return True else: return False def __repr__(self): if self: return "True" else: return "False" __str__ = __repr__ def __and__(self, other): if isinstance(other, bool): return bool(int(self) & int(other)) else: return int.__and__(self, other) __rand__ = __and__ def __or__(self, other): if isinstance(other, bool): return bool(int(self) | int(other)) else: return int.__or__(self, other) __ror__ = __or__ def __xor__(self, other): if isinstance(other, bool): return bool(int(self) ^ int(other)) else: return int.__xor__(self, other) __rxor__ = __xor__ # Bootstrap truth values through sheer willpower False = int.__new__(bool, 0) True = int.__new__(bool, 1) The values False and True will be singletons, like None; the C implementation will not allow other instances of bool to be created. At the C level, the existing globals Py_False and Py_True will be identical to the built-in singletons False and True. All built-in operations that are defined to return a Boolean result will be changed to return False or True instead of 0 or 1. In particular, this affects comparisons (<, <=, ==, !=, >, >=, is, is not, in, not it), the unary operator 'not', the built-in functions callable(), hasattr(), isinstance() and issubclass(), the dict method has_key(), the string and unicode methods endswith(), isalnum(), isalpha(), isdigit(), islower(), isspace(), istitle(), isupper(), and startswith(), the unicode methods isdecimal() and isnumeric(), and the closed attribute of file objects. Note that subclassing from int means that True+1 is valid and equals 2, and so on. This is important for backwards compatibility: because comparisons and so on currently return integer values, there's no way of telling what uses existing applications make of these values. Compatibility Because of backwards compatibility, the bool type lacks many properties that some would like to see. For example, arithmetic operations with one or two bool arguments is allowed, treating False as 0 and True as 1. Also, a bool may be used as a sequence index. I don't see this as a problem, and I don't want evolve the language in this direction either; I don't believe that a stricter interpretation of "Booleanness" makes the language much clearer. Another consequence of the compatibility requirement is that the expression "True and 6" has the value 6, and similarly the expression "False or 0" has the value 0. The "and" and "or" operators are usefully defined to return the first argument that determines the outcome. Of course, if both arguments are bools, the outcome is always a bool. It can also easily be coerced into being a bool by writing for example "bool(x and y)". Issues Because the repr() or str() of a bool value is different from an int value, some code (for example doctest-based unit tests, and possibly database code that relies on things like "%s" % truth) may fail. How much of a backwards compatibility problem this will be, I don't know. If we this turns out to be a real problem, we could changes the rules so that str() of a bool returns "0" or "1", while repr() of a bool still returns "False" or "True". Other languages (C99, C++, Java) name the constants "false" and "true", in all lowercase. In Python, I prefer to stick with the example set by the existing built-in constants, which all use CapitalizedWords: None, Ellipsis, NotImplemented (as well as all built-in exceptions). Python's built-in module uses all lowercase for functions and types only. But I'm willing to consider the lowercase alternatives if enough people think it looks better. Implementation An experimental, but fairly complete implementation in C has been uploaded to the SourceForge patch manager: http://sourceforge.net/tracker/index.php?func=detail&aid=528022&group_id=5470&atid=305470 Copyright This document has been placed in the public domain. Local Variables: mode: indented-text indent-tabs-mode: nil fill-column: 70 End: