[Python-Dev] ACCEPTED: PEP 285

Andrew P. Lentvorski bsder@allcaps.org
Wed, 3 Apr 2002 19:12:03 -0800 (PST)


I love the idea of a bool type, but please don't inherit bool from int.

I didn't want to chime in before because I thought Ka-Ping Yee covered
what a "real boolean" is better than I could, but his email didn't elicit
much comment.

The main disadvantage to a bool inheriting from an int is that there is no
way that the Python interpreter can check to make sure that it really gets
a bool if it inherits from int.  The only way to check if you got a real
bool is if the end programmer writes something using isinstance().

For compatibility, having True and False equate to 1 and 0, respectively,
is a good idea.  But please do it by promotion or conversion or something,
not inheritance.  Once the assumption of bool-is-an-int gets locked into
the language, it will be impossible to switch to
bool-only-looks-like-an-int or bool-is-a-real-type later.

If bool is a separate type, Python can have a --anal-bool (name
specifically chosen to be memorable ;) option which means "By gosh, if it
isn't a bool and it should be, throw something."  If bool inherits from
int, I see no way to ever implement that check in the language.  Please
correct me if this is an erroneous assumption.

As a concrete example, I have a VLSI layout tool written completely in
Python.  Because I and my colleagues are disciples of the Cult of Paranoid
Programming(tm), the codebase of 7674 lines includes 31 lines (counting
the else and complaint as one line) with checks of the following form:

>>> def checkme(shouldBeBoolean):
...     if shouldBeBoolean == 0:
...             print "False here"
...     elif shouldBeBoolean == 1:
...             print "True here"
...     else:
...             print "Evil person!!!  Don't hand me a non-boolean"
...
>>> checkme(0)
False here
>>> checkme(1)
True here
>>> checkme([])
Evil person!!!  Don't hand me a non-boolean
>>> checkme("anything")
Evil person!!!  Don't hand me a non-boolean

That means that about .5-1% (depending on how you really count the
checking lines) of the code exists solely to check to make sure that a
bool really is a bool.  And it's drudgery, boilerplate code that adds no
functionality to the program.

This practice got adopted because we were running down too many bugs which
started from [] or None sliding through as false and then causing subtle
problems later in the program when it could have been caught and fixed
immediately.  However, to catch these bugs requires a programmer to write
the extra check.  With --anal-bool: the above sequence becomes:

>>> def checkme(shouldBeBoolean):
...     if shouldBeBoolean:
...             print "True here"
...     else:
...             print "False here"

With --anal-bool:

>>> checkme(False)
False here
>>> checkme(True)
True here
>>> checkme(0)
Exception: ...
>>> checkme(1)
Exception: ...
>>> checkme([])
Exception: ...
>>> checkme("anything")
Exception: ...

Without --anal-bool:

>>> checkme(False)
False here
>>> checkme(True)
True here
>>> checkme(0)
False here
>>> checkme(1)
True here
>>> checkme([])
False Here
>>> checkme("anything")
True here

By leaving the default as loose, the backward compatibility is preserved
while still allowing stricter semantics.  By having --anal-bool as a
flag, I can remove .5-1% of my total codebase.  And we all know that the
only bug-free code is code that doesn't exist. ;)

The --anal-bool flag will also help point out all those places in the
Python code itself which will have to be changed to True and False.  And
do so loudly. ;)

-a