python: 可变对象的 id() - 解释有趣的模式?
python: id() of mutable object - explanation interesting pattern?
以下模式在调用具有相等值的可变对象的标识时出现。
如您所见,由 id(mutObj)
编辑的值 return 并不完全独立于 id(mutObj)
的先前 return 值,但模式不稳定。
此行为对于 Python 代码本身可能无关紧要,但我非常有兴趣了解底层机制!
>>> id([1,2])
6706248
>>> id([1,2])
59597256
>>> id([1,2])
56866632
>>> id([1,2])
56866632
>>> id([1,2])
56881992
>>> id([1,2])
56881992
>>> id([1,2])
56879624
>>> id([1,2])
56867784
>>> id([1,2])
56867784
>>> id([1,2])
56879624
Python 3.4.3 [MSC v.1600 64 位 (AMD64)] on win32
请特别注意,最后一个值等于前面 return 三个调用的值。
立即 re-use 的 id
Python 对您创建的所有对象使用相同的 id
:
>>> for x in range(10):
print(id([1, 2]))
4479841736
4479841736
4479841736
4479841736
4479841736
4479841736
4479841736
4479841736
4479841736
4479841736
因为没有对创建列表的引用,它会立即被垃圾回收,id
将是 re-used。
重复使用同一个名字
将列表分配给名称 obj
,将使列表保持活动状态,直到将新列表分配给相同的名称:
>>> for x in range(10):
obj = [1, 2]
print(id(obj))
4486925128
4486925192
4486925128
4486925192
4486925128
4486925192
4486925128
4486925192
4486925128
4486925192
在第二次迭代中 obj
存在并且 obj = [1, 2]
在分配给 obj
之前先创建新列表。分配后,旧列表将被垃圾收集,id
再次可用于 re-use。在接下来的每次迭代中重复此操作。
保留参考
当您在列表中保留对所有已创建列表的引用时:
>>> objs = []
>>> for x in range(10):
obj = [1, 2]
print(id(obj))
objs.append(obj)
4480011848
4483963144
4486916488
4486914376
4486914568
4486916616
4486914824
4486915016
4486915272
4486915464
Python 必须对所有这些使用不同的 id
。
口译效果
在标准交互式提示 (Python 3.5.1) 下工作,我可以生成:
>>> id([1, 2])
4330529608
>>> id([1, 2])
4330529608
>>> id([1, 2])
4330529608
>>> id([1, 2])
4330529608
>>> id([1, 2])
4330529608
>>> id([1, 2])
4330529608
但是在 IPython 或 IPython Notebook 中工作,您会得到:
In [1]: id([1, 2])
Out[1]: 4359684552
In [2]: id([1, 2])
Out[2]: 4379935816
In [3]: id([1, 2])
Out[3]: 4373482696
In [4]: id([1, 2])
Out[4]: 4359674248
In [5]: id([1, 2])
Out[5]: 4373482696
这是因为 IPython 在后台做了更多工作并创建了 re-use 释放的对象 id
,然后才能创建新对象。
引自the docs(强调我的):
id
(
object
)
Return the “identity” of an object. This is an 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.
CPython implementation detail: This is the address of the object in
memory.
基本上,当您编写 id([1, 2])
时,您创建了一个列表,检查它的 id
,然后将其丢弃,这使得它符合垃圾收集的条件。在 CPython 中,由于通过引用计数进行垃圾回收,它随后被删除,并且没有什么禁止在内存中完全相同的位置创建另一个对象,因此具有相同的 id
.
以下模式在调用具有相等值的可变对象的标识时出现。
如您所见,由 id(mutObj)
编辑的值 return 并不完全独立于 id(mutObj)
的先前 return 值,但模式不稳定。
此行为对于 Python 代码本身可能无关紧要,但我非常有兴趣了解底层机制!
>>> id([1,2])
6706248
>>> id([1,2])
59597256
>>> id([1,2])
56866632
>>> id([1,2])
56866632
>>> id([1,2])
56881992
>>> id([1,2])
56881992
>>> id([1,2])
56879624
>>> id([1,2])
56867784
>>> id([1,2])
56867784
>>> id([1,2])
56879624
Python 3.4.3 [MSC v.1600 64 位 (AMD64)] on win32
请特别注意,最后一个值等于前面 return 三个调用的值。
立即 re-use 的 id
Python 对您创建的所有对象使用相同的 id
:
>>> for x in range(10):
print(id([1, 2]))
4479841736
4479841736
4479841736
4479841736
4479841736
4479841736
4479841736
4479841736
4479841736
4479841736
因为没有对创建列表的引用,它会立即被垃圾回收,id
将是 re-used。
重复使用同一个名字
将列表分配给名称 obj
,将使列表保持活动状态,直到将新列表分配给相同的名称:
>>> for x in range(10):
obj = [1, 2]
print(id(obj))
4486925128
4486925192
4486925128
4486925192
4486925128
4486925192
4486925128
4486925192
4486925128
4486925192
在第二次迭代中 obj
存在并且 obj = [1, 2]
在分配给 obj
之前先创建新列表。分配后,旧列表将被垃圾收集,id
再次可用于 re-use。在接下来的每次迭代中重复此操作。
保留参考
当您在列表中保留对所有已创建列表的引用时:
>>> objs = []
>>> for x in range(10):
obj = [1, 2]
print(id(obj))
objs.append(obj)
4480011848
4483963144
4486916488
4486914376
4486914568
4486916616
4486914824
4486915016
4486915272
4486915464
Python 必须对所有这些使用不同的 id
。
口译效果
在标准交互式提示 (Python 3.5.1) 下工作,我可以生成:
>>> id([1, 2])
4330529608
>>> id([1, 2])
4330529608
>>> id([1, 2])
4330529608
>>> id([1, 2])
4330529608
>>> id([1, 2])
4330529608
>>> id([1, 2])
4330529608
但是在 IPython 或 IPython Notebook 中工作,您会得到:
In [1]: id([1, 2])
Out[1]: 4359684552
In [2]: id([1, 2])
Out[2]: 4379935816
In [3]: id([1, 2])
Out[3]: 4373482696
In [4]: id([1, 2])
Out[4]: 4359674248
In [5]: id([1, 2])
Out[5]: 4373482696
这是因为 IPython 在后台做了更多工作并创建了 re-use 释放的对象 id
,然后才能创建新对象。
引自the docs(强调我的):
id
(
object
)
Return the “identity” of an object. This is an 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.CPython implementation detail: This is the address of the object in memory.
基本上,当您编写 id([1, 2])
时,您创建了一个列表,检查它的 id
,然后将其丢弃,这使得它符合垃圾收集的条件。在 CPython 中,由于通过引用计数进行垃圾回收,它随后被删除,并且没有什么禁止在内存中完全相同的位置创建另一个对象,因此具有相同的 id
.