[英]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? 注意
x
和y
的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.