Python 对新实例交替的引用 [英] Python reference to an new instance alternating

查看:56
本文介绍了Python 对新实例交替的引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这几天我一直在玩 Python,我意识到 Python 将 id(address) 分配给新实例(int 和 list)的一些有趣方式.

例如,如果我用一个数字(或两个不同的数字)调用 id 函数,它返回相同的结果.例如

<预><代码>>>>身份证(12345)4298287048>>>身份证(12345)4298287048>>>身份证(12345)4298287048>>>id(12342) #这里的数字不同,但仍然是相同的id4298287048

此外,当我先声明变量然后用它调用 id() 时,结果会像这样交替.

<预><代码>>>>x = [];编号(x)4301901696>>>x = [];编号(x)4301729448>>>x = [];编号(x)4301901696>>>x = [];编号(x)4301729448

有人可以解释一下这背后的 Python 工作吗?另外,是否有书籍或网站可以让我阅读有关 Python 的这部分内容(分配内存地址、幕后工作等),因为我从 python 文档

解决方案

您正在创建一个新对象没有任何其他引用,并且在 没有任何其他引用后,当对象再次被销毁时,Python 会重新使用内存位置code>id() 就完成了.在 CPython 中,id() 恰好 的结果是对象的内存位置.来自 id() 函数文档:

<块引用>

CPython 实现细节:这是对象在内存中的地址.

id(12345) 行创建了一个新的 int() 实例;因为它被绑定为 id() 的参数,所以它有 1 个引用.id() 确定内存位置,并返回该结果.在返回时,参数被清除并且对 int() 实例的引用计数下降到 0,Python 将其清除.内存被释放.

下一行创建一个新的 int() 实例.同一位置有可用内存,因此可以重复使用.

相反,当您第一次绑定新对象没有名称时,您创建了对该对象的额外引用并且它没有被清除.内存不会被释放,一个新的对象将不得不使用一个新的内存地址.

这部分也有记录,同样来自 id() 文档:

<块引用>

这是一个整数(或长整数),它保证在此对象的生命周期内是唯一且恒定的.生命周期不重叠的两个对象可能具有相同的 id() 值.

强调我的.

重新绑定时(x = []x 已经设置)Python 首先创建一个新对象,然后 重新绑定 x 以指向该新对象.这会在创建新列表之后 解除旧列表的绑定.这意味着在创建新的列表对象时,旧的内存位置仍然被占用.

将其映射到特定步骤:

  1. 您使用 id() == 4301901696 创建一个对象.
  2. 4301901696 绑定到 x -> 4301901696 的引用计数为 1.
  3. 您使用 id() == 4301729448 创建一个对象.
  4. 4301901696x 解除绑定.4301901696 的引用计数降至 0 并从内存中清除.
  5. 4301729448 绑定到 x.4301729448 的引用计数为 1.
  6. 您创建了一个新对象,4301901696 为空,因此新对象获得 id() == 4301901696.
  7. 4301729448x 解除绑定.4301729448 的引用计数降至 0 并从内存中清除.
  8. 4301901696 绑定到 x.4301901696 的引用计数为 1.

这也是文档的一部分,赋值语句文档 告诉您什么订单分配发生在:

<块引用>

赋值语句计算表达式列表 [...] 并将单个结果对象从左到右分配给每个目标列表.

其中 表达式列表= 符号右侧的所有内容.

I have been playing with Python these days, and I realize some interesting way how Python assign id(address) to new instance (int and list).

For example, if I keep call id function with a number (or two different number), it return the same result. e.g.

>>> id(12345)
4298287048
>>> id(12345)
4298287048
>>> id(12345)
4298287048
>>> id(12342) #different number here, yet still same id
4298287048

Also when I declare the variable first and then call id() with it, the results are alternating like this.

>>> x = []; id(x)
4301901696
>>> x = []; id(x)
4301729448
>>> x = []; id(x)
4301901696
>>> x = []; id(x)
4301729448

Can someone please explain the Python work behind this? Also, is there a book or a site where I can read about this part of Python (assigning memory address, behind scene work, etc) since there is little I can find from python documentation

解决方案

You are creating a new object without any other references and Python re-uses the memory location when the object is destroyed again after id() is done with it. In CPython, the result of id() happens to be the memory location of the object. From the id() function documentation:

CPython implementation detail: This is the address of the object in memory.

The line id(12345) creates a new int() instance; because it is bound as an argument to id() it has 1 reference to it. id() determines the memory location, and returns that result. In returning, the arguments are cleaned up and the reference count to the int() instance drops to 0, and Python cleans it up. The memory is freed.

The next line creates a new int() instance. There is memory available at the same location, so it is reused.

When, instead, you first bind the new object no a name, you created an extra reference to the object and it is not cleared up. The memory is not freed, and a new object will have to use a new memory address.

This part too is documented, again from the id() documentation:

This is an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.

Emphasis mine.

When rebinding (x = [] when x is already set) Python first creates a new object, then rebinds x to point to that new object. This unbinds the old list after the new list is created. This means the old memory location is still occupied when the new list object is created.

To map that out to specific steps:

  1. You create an object with id() == 4301901696.
  2. 4301901696 is bound to x -> Reference count for 4301901696 is 1.
  3. You create an object with id() == 4301729448.
  4. 4301901696 is unbound from x. Reference count for 4301901696 drops to 0 and is cleared from memory.
  5. 4301729448 is bound to x. Reference count for 4301729448 is 1.
  6. You create a new object, 4301901696 is empty so the new object gets id() == 4301901696.
  7. 4301729448 is unbound from x. Reference count for 4301729448 drops to 0 and is cleared from memory.
  8. 4301901696 is bound to x. Reference count for 4301901696 is 1.
  9. etc.

This too is part of the documentation, the assignment statement documenation tells you what order assignment takes place in:

An assignment statement evaluates the expression list [...] and assigns the single resulting object to each of the target lists, from left to right.

where expression list is everything on the right-hand-side of the = symbol.

这篇关于Python 对新实例交替的引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆