是的,CPython重用了
id()值。 不要指望这些在Python程序中是唯一的 。
这是明确记载:
返回对象的“身份”。这是一个整数,可以保证在 此对象的生存期内 唯一且恒定 。 具有不重叠生存期的两个对象可能具有相同的id()值。
大胆强调我的。仅当对象 存在时 ,id才是唯一的。没有剩余引用的对象将从内存中删除,从而允许将该
id()值重新用于另一个对象,因此使用了
非重叠生命周期的 措辞。
请注意,这仅适用于CPython,这是python.org提供的标准实现。还有其他Python实现,例如IronPython,Jython和PyPy,它们对实现方式
id()都有自己的选择,因为它们每个都可以对如何处理内存和对象生存期做出不同的选择。
要解决您的特定问题:
- 在CPython中,
id()
是内存地址。新对象将被放入下一个可用的存储空间中,因此,如果特定的内存地址具有足够的空间来容纳下一个新对象,则该存储地址将被重用。创建相同大小的新对象时,您可以在解释器中看到以下内容:>>> id(1234)
4546982768
id(4321)
4546982768
的
1234字面创建一个新的整数对象,为此
id()产生一个数值。由于没有对该
int值的进一步引用,因此将其再次从内存中删除。但是使用不同的整数文字再次执行相同的表达式,很可能会看到相同的
id()值(运行垃圾回收破坏循环引用可能会释放更多的内存,因此您
也 不会
id()再次看到相同的值。
因此它 不是随机的 ,但在CPython中是内存分配算法的函数。
- 如果需要检查特定对象, 请保留对它的引用 。如果您只需要确保对象仍然处于“活动状态”,那么这可能是一个
weakref
较弱的参考 。
例如,先记录一个对象引用,然后再检查它:
import weakref# recordobject_ref = weakref.ref(some_object)# check if it's the same object stillsome_other_reference is object_ref() # only true if they are the same object
弱引用不会保留该对象还活着,但如果它 是 活的那么
object_ref()将返回它(它会返回
None其他)。
您可以使用这种机制来生成真正唯一的标识符,请参见下文。
- 要“破坏”对象,您要做的就是 删除 对该对象的 所有引用 。变量(本地和全局)是引用。其他对象的属性以及列表,元组,字典,集合等容器中的条目也是如此。
一旦所有对一个对象的引用都消失了,该对象上的引用计数就会降为0,然后在该位置被删除。
仅需要垃圾回收即可破坏 循环引用 ,即仅互相 引用的
对象,而无需进一步引用循环。因为这样的一个循环在没有帮助的情况下永远不会达到0的引用计数,因此垃圾收集器会定期检查这种循环并中断其中一个引用以帮助从内存中清除那些对象。
因此,通过删除对对象的所有引用,可以使它从内存中删除(释放)。如何实现取决于对象的引用方式。你可以要求译员告诉你哪些对象引用与给定对象
gc.get_referrers()的功能,但考虑到
不给你变量名
。它为您提供对象,例如字典对象,该对象是将
__dict__对象引用为全局对象的模块的属性,等等。对于完全在您控制之下的代码,最多
gc.get_referrers()用作提醒自己从何处引用对象的工具当您编写代码删除这些代码时。
如果必须在 Python应用程序 的生存期内具有唯一的标识符,则必须实现自己的工具。如果您的对象是可 哈希的
并且支持弱引用,那么您可以使用
WeakKeyDictionary实例将任意对象与UUID关联:
from weakref import WeakKeyDictionaryfrom collections import defaultdictfrom uuid import uuid4class UniqueIdMap(WeakKeyDictionary): def __init__(self, dict=None): super().__init__(self) # replace data with a defaultdict to generate uuids self.data = defaultdict(uuid4) if dict is not None: self.update(dict)uniqueidmap = UniqueIdMap()def uniqueid(obj): """Produce a unique integer id for the object. Object must me *hashable*. Id is a UUID and should be unique across Python invocations. """ return uniqueidmap[obj].int
这仍然产生整数,但因为他们是他们不太UUID的 保证 是唯一的,但可能你会 永远 在遇到同样的ID 你的
一生是不是被陨石击中小。
这样,即使对于具有非重叠生命周期的对象,这也会为您提供唯一的ID:
>>> class Foo:... pass...>>> id(Foo())4547149104>>> id(Foo()) # memory address reused4547149104>>> uniqueid(Foo())151797163173960170410969562162860139237>>> uniqueid(Foo()) # but you still get a unique UUID188632072566395632221804340107821543671



