Why were True and False changed to keywords in Pyt

2019-01-11 06:28发布

问题:

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?

回答1:

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.


回答2:

For two reasons, mainly:

  1. So people don't do a __builtin__.True = False prank hidden on a random module. (as explayned by devnull)
  2. Because keywords are faster than global builtins. In Python 2.x, the interpreter would have to resolve those variables' values before using them, which is a bit slower than keywords. (see Why is if True slower than if 1?)


回答3:

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".

  1. 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

  2. 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.

  3. 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