当你在Python中调用object.__repr__()方法时,你会得到类似这样的结果:

< __main__。测试对象位于0x2aba1c0cf890>

如果你重载__repr__(),除了调用super(Class, obj).__repr__()和reexing它,有没有任何方法来获得内存地址?


当前回答

你可以使用内置的'str'类型的'partition'方法获取任何对象的内存地址/位置。

下面是一个使用它来获取对象内存地址的例子:

Python 3.8.3 (default, May 27 2020, 02:08:17)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> object.__repr__(1)
'<int object at 0x7ca70923f0>'
>>> hex(int(object.__repr__(1).partition('object at ')[2].strip('>'), 16))
0x7ca70923f0
>>>

在这里,我使用内置的“对象”类“__repr__”方法与一个对象/项目如1作为参数返回字符串的字符串,然后我分区将返回一个元组的字符串之前我提供的字符串,我提供的字符串,然后我提供的字符串在字符串,以及内存位置定位后的物体”,我能得到它分区的内存地址的部分。

然后,由于内存地址作为返回元组中的第三项返回,我可以用索引2从元组中访问它。但是,它在我获得的字符串中有一个直角括号作为后缀,所以我使用'strip'函数来删除它,这将返回不带尖括号的字符串。然后,我将结果字符串转换为以16为基数的整数,然后将其转换为十六进制数。

其他回答

你可以这样重新实现默认的repr:

def __repr__(self):
    return '<%s.%s object at %s>' % (
        self.__class__.__module__,
        self.__class__.__name__,
        hex(id(self))
    )

只使用

id(object)

如果__repr__重载,你可以考虑__str__来查看变量的内存地址。

下面是Moshe Zadka在StackOverflow中__repr__和__str__的细节。

你可以使用内置的'str'类型的'partition'方法获取任何对象的内存地址/位置。

下面是一个使用它来获取对象内存地址的例子:

Python 3.8.3 (default, May 27 2020, 02:08:17)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> object.__repr__(1)
'<int object at 0x7ca70923f0>'
>>> hex(int(object.__repr__(1).partition('object at ')[2].strip('>'), 16))
0x7ca70923f0
>>>

在这里,我使用内置的“对象”类“__repr__”方法与一个对象/项目如1作为参数返回字符串的字符串,然后我分区将返回一个元组的字符串之前我提供的字符串,我提供的字符串,然后我提供的字符串在字符串,以及内存位置定位后的物体”,我能得到它分区的内存地址的部分。

然后,由于内存地址作为返回元组中的第三项返回,我可以用索引2从元组中访问它。但是,它在我获得的字符串中有一个直角括号作为后缀,所以我使用'strip'函数来删除它,这将返回不带尖括号的字符串。然后,我将结果字符串转换为以16为基数的整数,然后将其转换为十六进制数。

这里有一些其他答案没有涵盖的问题。

首先,id只返回:

一个对象的“身份”。这是一个整数(或长整数),保证在此对象的生命周期内是唯一的常量。两个生命周期不重叠的对象可能具有相同的id()值。


In CPython, this happens to be the pointer to the PyObject that represents the object in the interpreter, which is the same thing that object.__repr__ displays. But this is just an implementation detail of CPython, not something that's true of Python in general. Jython doesn't deal in pointers, it deals in Java references (which the JVM of course probably represents as pointers, but you can't see those—and wouldn't want to, because the GC is allowed to move them around). PyPy lets different types have different kinds of id, but the most general is just an index into a table of objects you've called id on, which is obviously not going to be a pointer. I'm not sure about IronPython, but I'd suspect it's more like Jython than like CPython in this regard. So, in most Python implementations, there's no way to get whatever showed up in that repr, and no use if you did.


但是如果你只关心CPython呢?毕竟,这是很常见的情况。

首先,您可能注意到id是一个整数;*如果您想要0x2aba1c0cf890字符串而不是数字46978822895760,那么您必须自己格式化它。在被窝里,我相信对象。__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或相关类型的指针。对于那些相关的类型,你可以调用PyFoo_Check来确保它确实是一个Foo对象,然后使用(PyFoo *)p进行强制转换。因此,如果您正在编写一个C扩展,id正是您所需要的。

如果您正在编写纯Python代码呢?你可以在ctypes中使用pythonapi调用完全相同的函数。


最后,其他一些答案会出现ctypes.addressof。这与这里无关。这只适用于ctypes对象,如c_int32(可能还有一些类似内存缓冲区的对象,如numpy提供的对象)。即使在这里,它也没有给你c_int32值的地址,它给了你c_int32封装的c级int32的地址。

话虽如此,通常情况下,如果你真的认为你需要某个东西的地址,你一开始就不想要原生Python对象,你想要一个ctypes对象。