anomaly

Chris Angelico rosuav at gmail.com
Mon May 11 10:13:00 EDT 2015


On Mon, May 11, 2015 at 11:38 PM, Antoon Pardon
<antoon.pardon at rece.vub.ac.be> wrote:
> "We allow buitins to be overridden", doesn't sound as a very accurate
> description of the underlining reason, when you know that things have
> been removed from builtins and made a keyword in order to prevent them
> from being overridden.

There are principles, and then there are specific instances that go
against those principles. The overarching principle has its
justification; the violations have to have their own justifications.
As Steven said, there are no a priori reasons for most things - or to
put it another way, there are very few design decisions that come down
to a fundamental "this is right, this is wrong" - but there can be
strong and weak justifications for things.

Why does Python have most built-ins as simply looked-up names that can
be overridden? Because otherwise, there would be a veritable ton of
keywords:

>>> dir(builtins)
['ArithmeticError', 'AssertionError', 'AttributeError',
'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError',
'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError',
'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError',
'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError',
'Exception', 'False', 'FileExistsError', 'FileNotFoundError',
'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError',
'ImportError', 'ImportWarning', 'IndentationError', 'IndexError',
'InterruptedError', 'IsADirectoryError', 'KeyError',
'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError',
'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError',
'OSError', 'OverflowError', 'PendingDeprecationWarning',
'PermissionError', 'ProcessLookupError', 'ReferenceError',
'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopIteration',
'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit',
'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError',
'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError',
'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
'ValueError', 'Warning', 'ZeroDivisionError', '__build_class__',
'__debug__', '__doc__', '__import__', '__loader__', '__name__',
'__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin',
'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod',
'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict',
'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter',
'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr',
'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance',
'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map',
'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord',
'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed',
'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str',
'sum', 'super', 'tuple', 'type', 'vars', 'zip']

in addition to these, which _are_ keywords:

>>> keyword.kwlist
['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class',
'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for',
'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal',
'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with',
'yield']

Python 2 had 'print' as a keyword, and it was specifically turned into
a non-keyword in Python 3 to allow it to be overridden. It could have
been turned into a function while still being a keyword, but it
wasn't. Conversely, True and False became keywords, because there's no
practical reason to override them. [1] You may well want to shadow
'copyright' with your own program's copyright notice, given that the
built-in name is primarily there for interactive use. You might use
'input' to store the incoming text in a non-interactive program, or
'quit' in an interactive one to store a flag that becomes True when
the user wants to terminate. Very frequently, 'id' is used as a
database ID. None of these shadowings is a problem to the language;
chances are none of them will ever be a problem to your code either.
Having most of the built-in names *not* be keywords means that adding
new built-ins doesn't break code; code that used the name for some
other meaning will still work, but won't be able to use the new
feature. That's a good thing.

ChrisA

[1] http://thedailywtf.com/articles/What_Is_Truth_0x3f_ notwithstanding.



More information about the Python-list mailing list