访问对象内存地址
当你在Python中调用object.__repr__()
方法时,你会得到这样的结果:
< main。testing对象在0x2aba1c0cf890>
如果你重载__repr__()
,有没有办法获得内存地址的保留,否则调用super(Class, obj).__repr__()
并将其重新排列?
Python手册有关于id()
说法:
返回一个对象的“身份”。 这是一个整数(或长整数),在整个生命周期中保证它是唯一的,并且是常量。 两个具有非重叠生命周期的对象可能具有相同的id()值。 (实现注意:这是对象的地址。)
所以在CPython中,这将是对象的地址。 但是没有任何其他Python解释器的保证。
请注意,如果您正在编写C扩展,则可以完全访问Python解释器的内部,包括直接访问对象的地址。
你可以这样重新实现默认的repr:
def __repr__(self): return '<%s.%s object at %s>' % ( self.__class__.__module__, self.__class__.__name__, hex(id(self)) )
只是使用
id(object)
只是作为对Torsten的回应,我无法在常规python对象上调用addressof()
。 此外, id(a) != addressof(a)
。 这是CPython,不知道其他什么。
>>> from ctypes import c_int, addressof >>> a = 69 >>> addressof(a) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: invalid type >>> b = c_int(69) >>> addressof(b) 4300673472 >>> id(b) 4300673392
这里有几个问题没有被任何其他答案所覆盖。
首先, id
只返回:
对象的“身份”。 这是一个整数(或长整数),在整个生命周期中保证它是唯一的,并且是常量。 两个具有非重叠生命周期的对象可能具有相同的
id()
值。
在CPython中,这恰好是代表解释器中的对象的PyObject
的指针,这与object.__repr__
显示的内容是一样的。 但是这只是CPython的一个实现细节,而不是Python的一般情况。 Jython不处理指针,它处理Java引用(JVM当然可能表示为指针,但是由于GC允许移动它们,所以你不能看到那些指针)。 PyPy让不同的types有不同types的id
,但是最一般的只是一个你称为id
的对象表的索引,这显然不会是一个指针。 我不确定IronPython,但是我怀疑在这方面它比Jython更像CPython。 所以,在大多数的Python实现中,没有办法得到在repr
显示的任何东西,如果你这样做没有用处。
但是如果你只关心CPython呢? 毕竟,这是一个很常见的情况。
那么,首先,你可能会注意到id
是一个整数; *如果你想要的是0x2aba1c0cf890
而不是数字46978822895760
,你将不得不自己格式化。 在封面之下,我认为object.__repr__
最终是使用了printf
的%p
格式,而这些格式在Python中是没有的,但是你可以这样做:
format(id(spam), '#010x' if sys.maxsize.bit_length() <= 32 else '#18x')
*在3.x,这是一个int
。 在2.x中,如果它足够大以容纳一个指针(这可能不是由于某些平台上的签名数字问题),那么它是一个int
,否则就是一个很长的指针。
除了将这些指针打印出来之外,还有什么可以做的吗? 当然(同样,假设你只关心CPython)。
所有的C API函数都有一个指向PyObject
或相关types的指针。 对于那些相关的types,你可以调用PyFoo_Check
来确保它确实是一个Foo
对象,然后用(PyFoo *)p
。 所以,如果你正在编写一个C扩展,这个id
就是你所需要的。
如果你正在编写纯Python代码呢? 你可以调用pythonapi
从ctypes
完全相同的function。
最后,其他一些答案已经提出了ctypes.addressof
。 这在这里没有关系。 这只适用于像c_int32
这样的ctypes
对象(也可能是一些类似于内存缓冲区的对象,比如numpy
提供的对象)。 而且,即使在那里,它也没有给你c_int32
值的地址,它给了你c_int32
的C级int32
的地址。
话虽如此,如果你真的认为你需要某个东西的地址,你不需要一个原生的Python对象,你想要一个ctypes
对象。
随着ctypes ,你可以实现同样的事情
>>> import ctypes >>> a = (1,2,3) >>> ctypes.addressof(a) 3077760748L
文档:
addressof(C instance) -> integer
返回C实例内部缓冲区的地址
请注意,在CPython中,当前的id(a) == ctypes.addressof(a)
,但ctypes.addressof
应该返回每个Python实现的实际地址,if
- ctypes被支持
- 内存指针是一个有效的概念。
编辑 :增加了关于ctypes解释器独立的信息
您可以通过以下方式获得适合该目的的内容:
id(self)
虽然id(object)
在默认的CPython实现中获取对象的地址是正确的,但是这通常是无用的……对于来自纯Python代码的地址,你无能为力 。
唯一一次你真正能够使用这个地址的地方是来自一个C扩展库……在这种情况下,得到对象的地址是微不足道的,因为Python对象总是作为C指针传递的。