在您的问题中,您写道“解释器如何构建所有可能类型的完整列表”-但这包含错误的假设。没有可能的类型的完整列表。有一组有效的现有类型,但它们没有排列在列表中。
您有一个命名空间,它通常按特定顺序排列:函数(本地)、模块(全局)、内置。在解析代码时,编译器还为literals 选择类型构造函数。每个地方的每个名字都可以指代任何对象,其中有很多类型:
>>> [name for name in dir(__builtins__)
if isinstance(getattr(__builtins__,name), type)]
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
'BufferError', 'BytesWarning', 'DeprecationWarning', 'EOFError',
'EnvironmentError', 'Exception', 'FloatingPointError', 'FutureWarning',
'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError',
'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError',
'NameError', 'NotImplementedError', 'OSError', 'OverflowError',
'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError', 'RuntimeWarning',
'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
'SystemExit', 'TabError', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError',
'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning',
'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', 'basestring',
'bool', 'buffer', 'bytearray', 'bytes', 'classmethod', 'complex', 'dict',
'enumerate', 'file', 'float', 'frozenset', 'int', 'list', 'long', 'memoryview',
'object', 'property', 'reversed', 'set', 'slice', 'staticmethod', 'str', 'super',
'tuple', 'type', 'unicode', 'xrange']
解释器实际上并不关心有多少类型,只关心它们各自如何应用于解释要运行的代码。它通过使用每个对象都有的类型指针来发现:
>>> type(1)
<type 'int'>
结果是,如果两种类型都不合适,他们的工作就是告诉你:
>>> 1+"foo"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
>>> "foo"+1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects
>>>
第一个+实际上是int.__add__,第二个是str.__add__,只是通过左边的对象查找。 (像__radd__ 这样的替代尝试会变得有点复杂,但基本原理是一样的。)