简体   繁体   English

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

[英]How does Python interpreter work in dynamic typing?

I read this question, but it didn't give me a clear answer: How does Python interpreter look for types? 我读了这个问题,但它没有给我一个明确的答案: Python解释器如何寻找类型?

How does python interpreter know the type of a variable? python解释器如何知道变量的类型? I'm not looking how do get the type. 我不知道如何获得类型。 I'm here looking at what happens behind the scene. 我在这里看看幕后发生了什么。 In the example below, how does it associate the class int or string to my variable. 在下面的示例中,它如何将类int或string与我的变量相关联。

How does it know that is an int: 它是如何知道这是一个int:

>>> i = 123
>>> type(i) 
<class 'int'>

or that string: 或那个字符串:

>>> i = "123"
>>> type(i)
<class 'str'>

how does it associate the class int or string to my variable 它如何将类int或string与我的变量相关联

Python doesn't. Python没有。 Variables have no type . 变量没有类型 Only the object that a variable references has a type. 只有变量引用的对象具有类型。 Variables are simply names pointing to objects . 变量只是指向对象的名称

For example, the following also shows the type of an object, but no variable is involved : 例如,以下内容还显示了对象的类型,但不涉及任何变量

>>> type(1)
<class 'int'>
>>> type('foobar')
<class 'str'>

When you use type(variable) , the variable part of the expression simply returns the object that name references, passing in the object to the type() function. 当使用type(variable) ,则variable表达式的一部分简单地返回名称引用的对象,传递到物体type()函数。 When using 1 or 'foobar' , the expression is a literal producing the object, which is then passed to the type() function. 当使用1'foobar' ,表达式是生成对象的文字,然后传递给type()函数。

Python objects are simply datastructures in the interpreter memory; Python对象只是解释器内存中的数据结构; in CPython C structs are used. 在CPython C结构中使用。 Variables are merely references (pointers) to those structures. 变量只是那些结构的引用(指针)。 The basic type struct in CPython is called PyObject , and this struct has a ob_type slot that tells Python what type something is. CPython中的基本类型结构称为PyObject ,这个结构有一个ob_type ,告诉Python什么类型的东西。 Types are simply more C structures . 类型只是更多的C结构

If you wanted to follow along in the CPython source code, you'd start at the bltinmodule.c source code (since type is a built-in name), which defines type as the PyType_Type structure . 如果你想跟随CPython源代码,你可以从bltinmodule.c源码开始(因为type是内置名称),它将type定义为PyType_Type结构 Calling a type ( type is a type too) invokes their tp_new function , and PyType_Type defines that as the type_new function . 调用类型type也是类型 )调用它们的tp_new函数PyType_Type 将其定义type_new函数 This function handles calls with one argument as follows: 此函数使用一个参数处理调用,如下所示:

/* 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);
    }

Here x is the PyObject object you passed in; 这里x是你传入的PyObject对象; note, not a variable, but an object! 注意,不是变量,而是对象! So for your 1 integer object or 'foobar' string object, the Py_TYPE() macro result is returned. 因此,对于1整数对象或'foobar'字符串对象,将返回Py_TYPE()宏结果。 Py_TYPE is a macro that simply returns the ob_type value of any PyObject struct. Py_TYPE是一个宏ob_type返回任何PyObject结构的ob_type值。

So now you have the type object for either 1 or 'foobar' ; 所以现在你有1'foobar'的类型对象; how come you see <class 'int'> or <class 'str'> in your interpreter session? 你怎么在解释器会话中看到<class 'int'><class 'str'> The Python interactive interpreter automatically uses the repr() function on any expression results. Python交互式解释器自动在任何表达式结果上使用repr()函数 In the C structure for PyType_Type definitions the PyType_Type struct is incorporated so all the slots for that type are directly available; 在C结构PyType_Type定义中PyType_Type结构被结合,因此所有用于该类型的时隙是直接可用; I'll omit here exactly how that works. 我会在这里省略究竟是如何工作 For type objects, using repr() means the type_repr function is called which returns this: 对于类型对象,使用repr()表示调用type_repr函数 ,该函数返回:

rtn = PyUnicode_FromFormat("<class '%s'>", type->tp_name);

So in the end, type(1) gets the ->ob_type slot, (which turns out to be the PyLong_Type struct in Python 3, long story), and that structure has a tp_name slot set to "int" . 所以最后, type(1)得到->ob_type槽,(事实证明它是Python 3中的PyLong_Type结构 ,长篇故事),并且该结构的tp_name槽设置为"int"

TL;DR : Python variables have no type, they are simply pointers to objects. TL; DR :Python变量没有类型,它们只是指向对象的指针。 Objects have types, and the Python interpreter will follow a series of indirect references to reach the type name to print if you are echoing the object in your interpreter. 对象具有类型,如果您在解释器中回显对象,Python解释器将遵循一系列间接引用来到达要打印的类型名称。

The concept "type" of a variable is "implemented" by using objects of a specific class. 通过使用特定类的对象来“实现”变量的“类型”概念。

So in 所以

a=float()

an object of type float , as defined by the class float is returned by float() . 类型的对象float ,如由类定义float通过返回float() Python knows what type it is because that's how objects work: you know what type they are. Python知道它是什么类型,因为对象是如何工作的:你知道它们是什么类型。 a is now a float object, with value 0.0. a现在是一个float对象,值为0.0。

With builtins, it's the same, it's just that they have shorthands for declaring them. 对于内置,它是相同的,只是他们有简短的声明它们。

i=123

is the same as 是相同的

i=int(123)

int() returns an object of class integer, with value 123. int()返回类integer的对象,值为123。

similarly 同样

i="123"

is the same as 是相同的

i=str("123")

str("123") returns an object of class str, with value "123" str("123")返回str类的对象,值为“123”

Python variables have no type, they are just references to objects. Python变量没有类型,它们只是对象的引用。 The size of a reference is the same regardless of what it is referring to. 无论引用什么,引用的大小都是相同的。 In the C implementation of Python it is a pointer, and does have a type, it a pointer to a Python object: PyObject * . 在C Python实现它是一个指针,并确实有一个类型,它的指针到一个Python对象: PyObject * The pointer is the same type regardless of class of object. 无论对象类如何,指针都是相同的类型。 Objects, on the other hand, know which class they belong to. 另一方面,对象知道它们属于哪个类。

It has been argued that Python has no variables, only names, although that's a step too far for most people. 有人认为Python没有变量,只有名称,尽管对大多数人来说这是一个太过分的步骤。

References in the CPython implementation have an id (identifier) which is actually a virtual address. CPython实现中的引用具有id(标识符),其实际上是虚拟地址。 The detail and value of this address is not worth pursuing - it can (and probably will) change between versions and is not meant to be used for anything other than a unique number identifying the object. 这个地址的细节和价值不值得追求 - 它可以(并且可能会)在不同版本之间进行更改,并不意味着用于识别对象的唯一编号以外的任何其他内容。 Nevertheless it can provide interesting pointers (pardon the pun) to what is happening: 然而,它可以提供有趣的指针(原谅双关语)发生的事情:

>>> x = 42
>>> y = x
>>> id(x)
4297539264
>>> id(y)
4297539264

Note that the id (address) of x and y are the same - they are referencing the same object, an int with the value 42. So, what happens when we change x , does y change as well? 注意xy的id(地址)是相同的 - 它们引用同一个对象,一个值为42的int 。那么,当我们改变x时会发生什么, y也会改变吗?

>>> x = "hello"
>>> id(x)
4324832176
>>> id(y)
4297539264

Thankfully not. 谢天谢地。 Now x is just referring to a new object of class str with the value "Hello". 现在x只是引用类str的新对象,其值为“Hello”。

When we: 什么时候我们:

>>> id(y)
4297539264
>>> y = 37
>>> id(y)
4297539104 

The id of y changed! y的id改变了! This is because it is now referencing a different object. 这是因为它现在引用了一个不同的对象。 int s are immutable , so the assignment y = 37 did not change the original object (42) it created a new one. int不可变的 ,因此赋值y = 37没有改变原始对象(42)它创建了一个新对象。 The object with the value 42 has its reference count decremented and can now (in theory) be deleted. 值为42的对象的引用计数递减,现在(理论上)可以删除。 In practice it would probably remain in memory for efficiency reason, but thats an implementation detail. 在实践中,出于效率原因,它可能会留在内存中,但这是一个实现细节。

However: 然而:

>>> a = [1,2,3,4]
>>> b = a
>>> id(a)
4324804808
>>> id(b)
4324804808
>>> a[0] = 99
>>> b
[99, 2, 3, 4]

So changing the list a has changed b ! 所以更改列表a 已经改变了b This is because lists are mutable , they can change. 这是因为列表是可变的 ,它们可以改变。 The assignment b = a only copied the reference, not the list. 赋值b = a只复制引用,而不是列表。 See copy in the standard library. 请参阅标准库中的copy

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM