In Python 2, we could reassign True
and False
(but not None
), but all three (True
, False
, and None
) were considered builtin variables. However, in Py3k all three were changed into keywords as per the docs.
From my own speculation, I could only guess that it was to prevent shenanigans like this which derive from the old True, False = False, True
prank. However, in Python 2.7.5, and perhaps before, statements such as None = 3
which reassigned None
raised SyntaxError: cannot assign to None
.
Semantically, I don't believe True
, False
, and None
are keywords, since they are at last semantically literals, which is what Java has done. I checked PEP 0 (the index) and I couldn't find a PEP explaining why they were changed.
Are there performance benefits or other reasons for making them keywords as opposed to literals or special-casing them like None
in python2?
Possibly because Python 2.6 not only allowed True = False
but also allowed you to say funny things like:
__builtin__.True = False
which would reset True
to False
for the entire process. It can lead to really funny things happening:
>>> import __builtin__
>>> __builtin__.True = False
>>> True
False
>>> False
False
>>> __builtin__.False = True
>>> True
False
>>> False
False
EDIT: As pointed out by Mike, the Python wiki also states the following under Core Language Changes:
- Make True and False keywords.
- Reason: make assignment to them impossible.
This was discussed some months ago on python-dev.
Having tons of links to the definition of True would be annoying, contrary to links to e.g. the nonlocal or with statements doc.
And things I conclude why True and False will make things "even finer".
re-bound as a side effect of functions called within the loop.
It's really easy to change True, such as:
def True():
print True
There is really no good use case for letting user code rebind the built-in names None, True, and False, making them keywords has almost only pluses.
Make program has to look-up "True" in symbol-table at each step just to find True has value True is far from intuitive. (that is why 1 is faster than True.)
x=compile('while 1: foop()', '', 'exec')
dis.dis(x)
0 SETUP_LOOP 19 (to 22)
3 JUMP_FORWARD 4 (to 10)
6 JUMP_IF_FALSE 11 (to 20)
9 POP_TOP
>> 10 LOAD_NAME 0 (foop)
13 CALL_FUNCTION 0
16 POP_TOP
17 JUMP_ABSOLUTE 10
>> 20 POP_TOP
21 POP_BLOCK
>> 22 LOAD_CONST 1 (None)
25 RETURN_VALUE
x=compile('while True: foop()', '', 'exec')
dis.dis(x)
0 SETUP_LOOP 19 (to 22)
>> 3 LOAD_NAME 0 (True)
6 JUMP_IF_FALSE 11 (to 20)
9 POP_TOP
10 LOAD_NAME 1 (foop)
13 CALL_FUNCTION 0
16 POP_TOP
17 JUMP_ABSOLUTE 3
>> 20 POP_TOP
21 POP_BLOCK
>> 22 LOAD_CONST 0 (None)
25 RETURN_VALUE
reference:
- http://mail.python.org/pipermail/python-checkins/2011-September/107641.html
- http://mail.python.org/pipermail/python-checkins/2012-January/110353.html
- https://groups.google.com/forum/#!searchin/comp.lang.python/False$20True$20keyword/comp.lang.python/65B6qWUf8wI/HwQ5pwnW7woJ
Beginning talk related to assigning to True and False:
- http://bugs.python.org/issue2349
- https://groups.google.com/forum/comp.lang.python/65B6qWUf8wI/HwQ5pwnW7woJ
some Aux Data:
PS: some number shows True/1:
[alex@lancelot test]$ timeit.py -c -s'import itertools as it' 'c=it.count()'
'while True:' ' if c.next()>99: break'
10000 loops, best of 3: 91 usec per loop
[alex@lancelot test]$ timeit.py -c -s'import itertools as it' 'c=it.count()'
'while 1:' ' if c.next()>99: break'
10000 loops, best of 3: 76 usec per loop