可以在python2.6中更改变量的id值吗?

时间:2018-04-24 16:06:19

标签: python

有人可以通过id命令帮助我理解与python中的值相关联的内存空间的概念:并澄清我对下面代码片段的疑虑: 案例1:

>>> a=10
>>> b=10
>>> id(a)
140732845308032
>>> id(b)
140732845308032

案例2: 但同时请看下面的行和python解释器的输出:

>>> c=257
>>> d=257
>>> id(c)
140732848419768
>>> id(d)
140732848419840

我还注意到包含0-256值的变量的id具有相同的id值,但超出此范围会开始变化。

另一个问题是我们可以通过任何机会修改变量的id值。建议我。

先谢谢。

2 个答案:

答案 0 :(得分:1)

您无法修改id。对象的id在实例化时分配,并且在对象的生命周期内不能更改。在CPython(标准解释器)中,它实际上是对象的内存地址,因此很明显它为什么不能改变;在其他一些Python实现中,它只是一个自动递增的整数,但你仍然无法改变它。

Python有时会重用不可变对象,尽管这是CPython独有的实现细节,而其他Pythons(甚至不同版本的CPython)可能表现不同。由于整数对象2无法更改,因此在任何给定情况下使用哪个实例并不重要;为了提高效率,Python因此保留了一小部分"整数而不是总是创造新的整数。 (目前这些是-5到256,包括在内。)

字符串是另一种可以重复使用的对象。字符串文字总是被重用,您可以强制其他字符串与intern()函数一起使用。

空元组是另一个不可再生的对象,它被重用并始终具有相同的id

如果您需要更改对象的id,并且它不是Python始终视为单例的那些对象之一,您会怎么做?复制它。对于某些类型,使用类型本身很容易完成;例如list(my_list)会创建具有不同ID的my_list副本。这是浅层副本:如果列表包含子列表,则不会复制这些副本,而是在原始列表和副本中同时显示对相同子列表的引用。

也可以使用切片表示法轻松复制列表对象,la my_list[:](如元组和其他序列一样)。

如果您需要完整副本,或者想要复制没有内置复制方式的对象,copy模块可以让您满意。

答案 1 :(得分:1)

id()函数给出了CPython中对象的内存地址。

但是,如果我们查看the implementation,我们可以看到-5 <= x < 257范围内的整数如何在内存中引用相同的地址。

这是通过启动它们的静态数组来完成的:

static PyLongObject small_ints[NSMALLNEGINTS + NSMALLPOSINTS];

在定义限制后调用:

#ifndef NSMALLPOSINTS
#define NSMALLPOSINTS           257
#endif
#ifndef NSMALLNEGINTS
#define NSMALLNEGINTS           5
#endif

现在,当创建一个新整数时,将调用PyLong_FromLong函数并调用此CHECK_SMALL_INT

然后该函数检查条件:

-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS

在调用最终将查找的get_small_int之前是数组中的值:

v = (PyObject *)&small_ints[ival + NSMALLNEGINTS]

就是这样,所以-5 <= x < 257范围内的整数都引用内存中的相同位置,但其他较大的整数都有自己独立的实例;从而导致id()函数的结果发生变化。