Python解释器如何查找类型?

时间:2014-08-18 12:13:30

标签: python

如果我写的话:

>>> a = float()

Python解释器如何知道在哪里查找类型' float'?

我知道'漂浮'是Lib / types.py中定义的变量,是指内置类型types.FloatType。但是,解释器如何构建脚本所有可能类型的完整列表(包括用户定义和导入模块定义)?它看起来在哪些地方?我该怎么做才能在Python脚本中构建这样的列表?

3 个答案:

答案 0 :(得分:2)

您的问题似乎是,"这是一种类型声明?"答案是,它不是一种类型声明。 Python中的名称没有与之关联的类型。名称引用值,值具有在运行时确定的类型。

当Python执行a = float()时,它会查找名称float,并在内置函数中找到它,它是一个函数。它调用没有参数的函数。返回值是一个float对象。然后使名称a引用该对象。这就是全部。在它执行这行代码之前,Python不知道a将成为什么,并且它不知道将涉及浮点数。

Python是动态的,因此您的代码行可以在此程序中:

def float():
    return "I'm not a float!"

a = float()

现在执行a = float()时,内置函数与它无关,并且在任何地方都没有浮点数,而a指的是字符串。

有关名称和值的更多信息,请参阅Facts and Myths about Python Names and Values

答案 1 :(得分:1)

如果要将名称解析为全局,并且没有匹配的全局(您的模块中没有名为float的函数),则Python会查看{{1} } object是每个模块的全局命名空间的一部分。

该对象是一个内置模块,在C中定义。请参阅Python/bltinmodule.c

对于__builtins__,名称绑定到series of assignments中的C float结构,PyFloat_Type结构定义在Objects/floatobject.c中}

从根本上说,Python没有'类型声明&#39 ;; PyFloat_Typefloat等只是符合某种行为的C结构;它们生成的值在查询时Python可以识别为某种类型。因此,str生成的任何内容都会返回float()作为其类型。

并且因为float只是在您没有同名的全局信息时才会被咨询,您可以轻松提供__builtins__自己的实施赎回;一个在被调用时返回完全不同的东西。

如果要枚举所有内置类型对象,请遍历内置并枚举float()实例的任何内容:

type()

import __builtin__ for name, obj in vars(__builtin__).iteritems(): if isinstance(obj, type) and not issubclass(obj, BaseException): print name, obj 如何工作是CPython实现的实现细节,但是相同的对象公开为此处使用的__builtin__ module

请注意,您不可能希望收集代码可以生成的所有可能类型。函数可以生成函数本地的新类型,并且在模块全局中列出;类型不需要列在那里工作:

__builtins__

每次调用时,上面的函数都会生成带有 new 类型的对象(Python类也是类型)。您不会在模块全局变量中找到该类型,也不会在内置函数中找到该类型。

答案 2 :(得分:0)

在你的问题中,你写了“解释器如何构建所有可能类型的完整列表” - 但这包含一个错误的假设。没有完整的可能类型列表。有一组有效的现有类型,但它们没有列在列表中。

您有一个名称空间,通常按特定顺序查找:function(locals),module(globals),builtins。在解析代码时,编译器还为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__等替代尝试会变得更复杂,但基本原理是相同的。)