问题:访问对象存储器地址
当您object.__repr__()
在Python中调用该方法时,您会得到类似以下的信息:
<__main__.Test object at 0x2aba1c0cf890>
如果您过载了__repr__()
,还有什么方法可以保留该内存地址,然后调用super(Class, obj).__repr__()
并重新分配它呢?
回答 0
在Python的手册已经这样说id()
:
返回一个对象的“身份”,这是一个整数(或长整数),在该对象的生存期内保证是唯一且恒定的。两个不重叠生存期的对象可能具有相同的id()值。 (实施说明:这是对象的地址。)
因此,在CPython中,这将是对象的地址。但是,没有任何其他Python解释器的此类保证。
请注意,如果您正在编写C扩展名,则可以完全访问Python解释器的内部,包括直接访问对象的地址。
回答 1
您可以通过以下方式重新实现默认代表:
def __repr__(self):
return '<%s.%s object at %s>' % (
self.__class__.__module__,
self.__class__.__name__,
hex(id(self))
)
回答 2
只需使用
id(object)
回答 3
这里有一些其他答案未涵盖的问题。
首先,id
仅返回:
对象的“身份”。这是一个整数(或长整数),在该对象的生存期内,此整数保证是唯一且恒定的。具有非重叠生存期的两个对象可能具有相同的
id()
值。
在CPython中,这恰好是指向PyObject
解释器中代表对象的指针,这与on上的东西相同,显然不会成为指针。我不确定IronPython,但我怀疑在这方面,它更像是Jython,而不是CPython。因此,在大多数Python实现中,无法获得显示在其中的任何内容,如果您这样做了,则毫无用处。object.__repr__
显示。但这只是CPython的实现细节,而不是一般Python的真实情况。Jython不处理指针,它处理Java引用(JVM当然可以将其表示为指针,但是您看不到它们,并且也不想这样做,因为允许GC来回移动它们)。PyPy让不同类型的对象具有不同的种类id
,但最一般的只是对您已调用的对象表的索引id
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
如果它足够大以容纳一个指针(可能不是由于某些平台上的有符号数问题而引起的),long
否则是一个错误。
除了将它们打印出来,您还能使用这些指针做什么?当然(再次假设您只关心CPython)。
所有C API函数均采用指向PyObject
或相关类型的指针。对于那些相关的类型,您可以调用PyFoo_Check
以确保它确实是一个Foo
对象,然后使用进行强制转换(PyFoo *)p
。因此,如果您要编写C扩展名,id
则正是您所需要的。
如果您正在编写纯Python代码怎么办?您可以使用pythonapi
from 调用完全相同的函数ctypes
。
最后,提出了其他一些答案ctypes.addressof
。这与这里无关。这仅适用于ctypes
类似的对象c_int32
(可能还有一些类似内存缓冲区的对象,如所提供的对象numpy
)。而且,即使在那儿,它也没有为您提供c_int32
值的地址,而是为您提供int32
了c_int32
包装的C级地址。
话虽这么说,但通常情况下,如果您确实认为自己需要某个东西的地址,那么首先就不需要原生Python对象,而是想要一个ctypes
对象。
回答 4
仅作为对Torsten的回应,我无法调用addressof()
常规的python对象。此外,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
回答 5
使用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实现的真实地址,如果
- 支持ctypes
- 内存指针是一个有效的概念。
编辑:添加了有关ctypes解释器独立性的信息
回答 6
您可以通过以下方式获得适合该目的的东西:
id(self)
回答 7
我知道这是一个老问题,但是如果您现在仍在使用python 3编程,我实际上发现如果它是字符串,那么有一种非常简单的方法可以做到这一点:
>>> spam.upper
<built-in method upper of str object at 0x1042e4830>
>>> spam.upper()
'YO I NEED HELP!'
>>> id(spam)
4365109296
字符串转换也不影响内存中的位置:
>>> spam = {437 : 'passphrase'}
>>> object.__repr__(spam)
'<dict object at 0x1043313f0>'
>>> str(spam)
"{437: 'passphrase'}"
>>> object.__repr__(spam)
'<dict object at 0x1043313f0>'
回答 8
虽然确实id(object)
可以在默认的CPython实现中获取对象的地址,但这通常是无用的……您无法对纯Python代码中的地址进行任何操作。
实际上,唯一可以使用该地址的时间是来自C扩展库…在这种情况下,获取对象的地址很简单,因为Python对象始终作为C指针传递。