Python 解释器如何在动态类型中工作?
How does Python interpreter work in dynamic typing?
我看了这个问题,但没有给我一个明确的答案:
How does Python interpreter look for types?
python解释器如何知道变量的类型?我不是在看如何获得类型。我在这里查看幕后发生的事情。在下面的示例中,它如何将 class int 或 string 关联到我的变量。
它怎么知道那是一个整数:
>>> i = 123
>>> type(i)
<class 'int'>
或那个字符串:
>>> i = "123"
>>> type(i)
<class 'str'>
变量的概念"type"是"implemented"通过使用特定class的对象。
所以在
a=float()
float
类型的对象,由 class float
定义,由 float()
返回。 Python 知道它是什么类型,因为这就是对象的工作方式:您知道它们是什么类型。 a
现在是一个 float
对象,值为 0.0.
内置函数也是一样的,只是它们有声明它们的简写形式。
i=123
与
相同
i=int(123)
int()
returns 一个 class 整数对象,值为 123。
同样
i="123"
与
相同
i=str("123")
str("123")
returns class str 的对象,值为“123”
how does it associate the class int or string to my variable
Python 没有。 变量没有类型。只有变量引用的对象才有类型。变量只是 指向对象的名称 .
例如下面也显示了一个对象的类型,但是没有涉及变量:
>>> type(1)
<class 'int'>
>>> type('foobar')
<class 'str'>
当您使用 type(variable)
时,表达式的 variable
部分只是 returns name 引用的对象,传入 object到 type()
函数。当使用 1
或 'foobar'
时,表达式是生成对象的文字,然后传递给 type()
函数。
Python 对象只是解释器内存中的数据结构;在 CPython 中使用 C 结构。变量只是对这些结构的引用(指针)。 CPython 中的基本类型结构称为 PyObject
, and this struct has a ob_type
slot that tells Python what type something is. Types are simply more C structures.
如果您想继续学习 CPython 源代码,可以从 bltinmodule.c
source code (since type
is a built-in name), which defines type
as the PyType_Type
structure. Calling a type (type
is a type too) invokes their tp_new
function, and PyType_Type
defines that as the type_new
function 开始。此函数处理带有 one 参数的调用,如下所示:
/* 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);
}
这里x
就是你传入的PyObject
对象;注意,不是变量,而是对象!因此,对于您的 1
整数对象或 'foobar'
字符串对象,将返回 Py_TYPE()
宏结果。 Py_TYPE
is a macro 简单地 returns 任何 PyObject
结构的 ob_type
值。
所以现在你有了 1
或 'foobar'
的类型对象;你怎么会在口译会话中看到 <class 'int'>
或 <class 'str'>
? Python 交互式解释器自动使用 repr()
function on any expression results. In the C structure for PyType_Type
definitions the PyType_Type
struct is incorporated so all the slots for that type are directly available; I'll omit here exactly how that works. For type objects, using repr()
means the type_repr
function 调用 which returns this:
rtn = PyUnicode_FromFormat("<class '%s'>", type->tp_name);
所以最后,type(1)
得到了 ->ob_type
插槽,(原来是 PyLong_Type
struct in Python 3, long story), and that structure has a tp_name
slot set to "int"
.
TL;DR: Python 变量没有类型,它们只是指向对象的指针。 对象 有类型,如果您在解释器中回显对象,Python 解释器将遵循一系列间接引用以达到要打印的类型名称。
Python 变量没有类型,它们只是对对象的引用。无论引用的是什么,引用的大小都是相同的。在 Python 的 C 实现中它是一个指针,而 有一个类型,它是一个指向 Python 对象的指针:PyObject *
。不管对象的 class 是什么,指针都是相同的类型。另一方面,对象知道它们属于哪个class。
有人认为 Python 没有变量,只有名称,尽管这对大多数人来说太过分了。
CPython 实现中的引用有一个 id(标识符),它实际上是一个虚拟地址。这个地址的细节和价值不值得追求 - 它可以(并且可能会)在不同版本之间发生变化,并且除了标识对象的唯一编号外,不打算用于任何其他用途。然而,它可以为正在发生的事情提供有趣的指示(请原谅双关语):
>>> x = 42
>>> y = x
>>> id(x)
4297539264
>>> id(y)
4297539264
请注意 x
和 y
的 id(地址)是相同的——它们引用同一个对象,一个值为 42 的 int
。那么,会发生什么当我们改变 x
时,y
也会改变吗?
>>> x = "hello"
>>> id(x)
4324832176
>>> id(y)
4297539264
谢天谢地没有。现在 x
只是引用 class str
的一个新对象,其值为 "Hello"。
当我们:
>>> id(y)
4297539264
>>> y = 37
>>> id(y)
4297539104
y
的 id 变了!这是因为它现在引用了一个不同的对象。 int
是 不可变的 ,因此赋值 y = 37
没有更改原始对象 (42) 它创建了一个新对象。值为 42 的对象的引用计数已减少,现在(理论上)可以删除。实际上,出于效率原因,它可能会保留在内存中,但那是一个实现细节。
但是:
>>> a = [1,2,3,4]
>>> b = a
>>> id(a)
4324804808
>>> id(b)
4324804808
>>> a[0] = 99
>>> b
[99, 2, 3, 4]
所以更改列表 a
已经 更改 b
!这是因为列表 可变 ,它们可以更改。赋值 b = a
只复制了引用,而不是列表。请参阅标准库中的 copy。
我看了这个问题,但没有给我一个明确的答案: How does Python interpreter look for types?
python解释器如何知道变量的类型?我不是在看如何获得类型。我在这里查看幕后发生的事情。在下面的示例中,它如何将 class int 或 string 关联到我的变量。
它怎么知道那是一个整数:
>>> i = 123
>>> type(i)
<class 'int'>
或那个字符串:
>>> i = "123"
>>> type(i)
<class 'str'>
变量的概念"type"是"implemented"通过使用特定class的对象。
所以在
a=float()
float
类型的对象,由 class float
定义,由 float()
返回。 Python 知道它是什么类型,因为这就是对象的工作方式:您知道它们是什么类型。 a
现在是一个 float
对象,值为 0.0.
内置函数也是一样的,只是它们有声明它们的简写形式。
i=123
与
相同i=int(123)
int()
returns 一个 class 整数对象,值为 123。
同样
i="123"
与
相同i=str("123")
str("123")
returns class str 的对象,值为“123”
how does it associate the class int or string to my variable
Python 没有。 变量没有类型。只有变量引用的对象才有类型。变量只是 指向对象的名称 .
例如下面也显示了一个对象的类型,但是没有涉及变量:
>>> type(1)
<class 'int'>
>>> type('foobar')
<class 'str'>
当您使用 type(variable)
时,表达式的 variable
部分只是 returns name 引用的对象,传入 object到 type()
函数。当使用 1
或 'foobar'
时,表达式是生成对象的文字,然后传递给 type()
函数。
Python 对象只是解释器内存中的数据结构;在 CPython 中使用 C 结构。变量只是对这些结构的引用(指针)。 CPython 中的基本类型结构称为 PyObject
, and this struct has a ob_type
slot that tells Python what type something is. Types are simply more C structures.
如果您想继续学习 CPython 源代码,可以从 bltinmodule.c
source code (since type
is a built-in name), which defines type
as the PyType_Type
structure. Calling a type (type
is a type too) invokes their tp_new
function, and PyType_Type
defines that as the type_new
function 开始。此函数处理带有 one 参数的调用,如下所示:
/* 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);
}
这里x
就是你传入的PyObject
对象;注意,不是变量,而是对象!因此,对于您的 1
整数对象或 'foobar'
字符串对象,将返回 Py_TYPE()
宏结果。 Py_TYPE
is a macro 简单地 returns 任何 PyObject
结构的 ob_type
值。
所以现在你有了 1
或 'foobar'
的类型对象;你怎么会在口译会话中看到 <class 'int'>
或 <class 'str'>
? Python 交互式解释器自动使用 repr()
function on any expression results. In the C structure for PyType_Type
definitions the PyType_Type
struct is incorporated so all the slots for that type are directly available; I'll omit here exactly how that works. For type objects, using repr()
means the type_repr
function 调用 which returns this:
rtn = PyUnicode_FromFormat("<class '%s'>", type->tp_name);
所以最后,type(1)
得到了 ->ob_type
插槽,(原来是 PyLong_Type
struct in Python 3, long story), and that structure has a tp_name
slot set to "int"
.
TL;DR: Python 变量没有类型,它们只是指向对象的指针。 对象 有类型,如果您在解释器中回显对象,Python 解释器将遵循一系列间接引用以达到要打印的类型名称。
Python 变量没有类型,它们只是对对象的引用。无论引用的是什么,引用的大小都是相同的。在 Python 的 C 实现中它是一个指针,而 有一个类型,它是一个指向 Python 对象的指针:PyObject *
。不管对象的 class 是什么,指针都是相同的类型。另一方面,对象知道它们属于哪个class。
有人认为 Python 没有变量,只有名称,尽管这对大多数人来说太过分了。
CPython 实现中的引用有一个 id(标识符),它实际上是一个虚拟地址。这个地址的细节和价值不值得追求 - 它可以(并且可能会)在不同版本之间发生变化,并且除了标识对象的唯一编号外,不打算用于任何其他用途。然而,它可以为正在发生的事情提供有趣的指示(请原谅双关语):
>>> x = 42
>>> y = x
>>> id(x)
4297539264
>>> id(y)
4297539264
请注意 x
和 y
的 id(地址)是相同的——它们引用同一个对象,一个值为 42 的 int
。那么,会发生什么当我们改变 x
时,y
也会改变吗?
>>> x = "hello"
>>> id(x)
4324832176
>>> id(y)
4297539264
谢天谢地没有。现在 x
只是引用 class str
的一个新对象,其值为 "Hello"。
当我们:
>>> id(y)
4297539264
>>> y = 37
>>> id(y)
4297539104
y
的 id 变了!这是因为它现在引用了一个不同的对象。 int
是 不可变的 ,因此赋值 y = 37
没有更改原始对象 (42) 它创建了一个新对象。值为 42 的对象的引用计数已减少,现在(理论上)可以删除。实际上,出于效率原因,它可能会保留在内存中,但那是一个实现细节。
但是:
>>> a = [1,2,3,4]
>>> b = a
>>> id(a)
4324804808
>>> id(b)
4324804808
>>> a[0] = 99
>>> b
[99, 2, 3, 4]
所以更改列表 a
已经 更改 b
!这是因为列表 可变 ,它们可以更改。赋值 b = a
只复制了引用,而不是列表。请参阅标准库中的 copy。