我读过这个问题,但它没有给我一个明确的答案: How does Python interpreter look for types?
python解释器如何知道变量的类型?我不知道如何获得类型。我在这里看看幕后发生了什么。在下面的示例中,它如何将类int或string与我的变量相关联。
它是如何知道这是一个int:
>>> i = 123
>>> type(i)
<class 'int'>
或那个字符串:
>>> i = "123"
>>> type(i)
<class 'str'>
答案 0 :(得分:10)
如何将类int或string与我的变量
相关联
Python没有。 变量没有类型。只有变量引用的对象具有类型。变量只是指向对象的名称。
例如,以下内容还显示了对象的类型,但不涉及变量:
>>> type(1)
<class 'int'>
>>> type('foobar')
<class 'str'>
当您使用type(variable)
时,表达式的variable
部分只返回名称引用的对象,将对象传递给type()
函数。使用1
或'foobar'
时,表达式是生成对象的文字,然后传递给type()
函数。
Python对象只是解释器内存中的数据结构;在CPython C结构中使用。变量只是那些结构的引用(指针)。 CPython中的基本类型结构称为PyObject
,这个结构有一个ob_type
slot,告诉Python什么类型的东西。类型只是more C structures。
如果您想在CPython源代码中进行操作,请从bltinmodule.c
source code开始(因为type
是内置名称),defines type
as the PyType_Type
structure。调用类型(type
也是类型)会调用tp_new
function和PyType_Type
defines that作为{{ 3}}。此函数使用一个参数处理调用,如下所示:
/* 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()
宏结果。 the type_new
function只返回任何ob_type
结构的PyObject
值。
现在您拥有1
或'foobar'
的类型对象;你怎么在翻译会议上看到<class 'int'>
或<class 'str'>
? Python交互式解释器自动在任何表达式结果上使用Py_TYPE
is a macro。在PyType_Type
定义的C结构中,PyType_Type
结构被合并,因此该类型的所有插槽都可直接使用;我在这里完全省略 的工作方式。对于类型对象,使用repr()
表示调用repr()
function,返回此内容:
rtn = PyUnicode_FromFormat("<class '%s'>", type->tp_name);
最后,type(1)
获取->ob_type
广告位(事实证明,这是Python 3中的type_repr
function,长篇故事),该结构有{{3} }}
TL; DR :Python变量没有类型,它们只是指向对象的指针。 Objects 具有类型,如果您在解释器中回显对象,Python解释器将遵循一系列间接引用来访问要打印的类型名称。
答案 1 :(得分:0)
概念&#34;类型&#34;变量是&#34;实现&#34;通过使用特定类的对象。
所以在
a=float()
类float
的对象,由类float
定义,由float()
返回。 Python知道它是什么类型,因为对象是如何工作的:你知道它们是什么类型。 a
现在是float
对象,值为0.0。
对于内置版本,它是相同的,只是因为他们有缩写来声明它们。
i=123
与
相同 i=int(123)
int()
返回类integer的对象,值为123。
i="123"
与
相同 i=str("123")
str("123")
返回str类的对象,值为&#34; 123&#34;
答案 2 :(得分:0)
Python变量没有类型,它们只是对象的引用。无论引用什么,引用的大小都是相同的。在Python的C实现中,它是一个指针, 有一个类型,它是一个指向Python对象的指针:PyObject *
。无论对象类如何,指针都是相同的类型。另一方面,对象知道它们属于哪个类。
有人认为Python没有变量,只有名称,尽管对于大多数人来说这是一个太过分的步骤。
CPython实现中的引用具有id(标识符),其实际上是虚拟地址。这个地址的细节和价值不值得追求 - 它可以(并且可能会)在不同版本之间进行更改,并不意味着用于识别对象的唯一编号以外的任何其他内容。然而,它可以提供有趣的指针(原谅双关语)正在发生的事情:
>>> x = 42
>>> y = x
>>> id(x)
4297539264
>>> id(y)
4297539264
请注意x
和y
的ID(地址)相同 - 它们引用相同的对象,int
,其值为42.因此,当我们发生时会发生什么更改x
,y
也会更改吗?
>>> x = "hello"
>>> id(x)
4324832176
>>> id(y)
4297539264
谢天谢地没有。现在x
只是引用类str
的新对象,其值为&#34; Hello&#34;。
当我们:
>>> 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。