Python解释器如何在动态类型中工作?

vin*_*ngo 6 python dynamic-typing python-internals

我读了这个问题,但它没有给我一个明确的答案: Python解释器如何寻找类型?

python解释器如何知道变量的类型?我不知道如何获得类型.我在这里看看幕后发生了什么.在下面的示例中,它如何将类int或string与我的变量相关联.

它是如何知道这是一个int:

>>> i = 123
>>> type(i) 
<class 'int'>
Run Code Online (Sandbox Code Playgroud)

或那个字符串:

>>> i = "123"
>>> type(i)
<class 'str'>
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 11

它如何将类int或string与我的变量相关联

Python没有.变量没有类型.只有变量引用的对象具有类型.变量只是指向对象的名称.

例如,以下内容还显示了对象的类型,但不涉及任何变量:

>>> type(1)
<class 'int'>
>>> type('foobar')
<class 'str'>
Run Code Online (Sandbox Code Playgroud)

当您使用type(variable)时,variable表达的一部分,只是返回名称引用的对象,传递对象type()功能.当使用1or时'foobar',表达式是生成对象的文字,然后传递给type()函数.

Python对象只是解释器内存中的数据结构; 在CPython C结构中使用.变量只是那些结构的引用(指针).调用CPython中的基本类型结构PyObject,这个结构有一个ob_type,告诉Python什么类型的东西.类型只是更多的C结构.

如果你想跟随CPython源代码,你可以从bltinmodule.c源代码开始(因为它type是一个内置名称),它定义typePyType_Type结构.调用类型(type太)调用其tp_new功能,并且定义了作为所述函数.此函数使用一个参数处理调用,如下所示:PyType_Type type_new

/* Special case: type(x) should return x->ob_type */
{
    const Py_ssize_t nargs = PyTuple_GET_SIZE(args);
    const Py_ssize_t nkwds = kwds == NULL ? 0 : PyDict_Size(kwds);

    if (PyType_CheckExact(metatype) && nargs == 1 && nkwds == 0) {
        PyObject *x = PyTuple_GET_ITEM(args, 0);
        Py_INCREF(Py_TYPE(x));
        return (PyObject *) Py_TYPE(x);
    }
Run Code Online (Sandbox Code Playgroud)

xPyObject你传入的对象; 注意,不是变量,而是对象!因此,对于1整数对象或'foobar'字符串对象,将Py_TYPE()返回宏结果.Py_TYPE是一个宏,只返回ob_type任何PyObject结构的值.

所以,现在你有两种类型的对象1'foobar'; 你怎么看到<class 'int'><class 'str'>在你的翻译会议中?Python交互式解释器自动在任何表达式结果上使用该repr()函数.在用于PyType_Type定义的C结构中,PyType_Type结构被合并,因此该类型的所有插槽都是直接可用的; 我会在这里省略究竟如何工作的.对于类型对象,使用repr()意味着调用该type_repr函数,该函数返回:

rtn = PyUnicode_FromFormat("<class '%s'>", type->tp_name);
Run Code Online (Sandbox Code Playgroud)

所以最后,type(1)获取->ob_type插槽,(原来是Python 3中的PyLong_Type结构,长篇故事),并且该结构的tp_name插槽设置为"int".

TL; DR:Python变量没有类型,它们只是指向对象的指针.对象具有类型,如果您在解释器中回显对象,Python解释器将遵循一系列间接引用来到达要打印的类型名称.