当你在Python中调用object.__repr__()方法时,你会得到类似这样的结果:
< __main__。测试对象位于0x2aba1c0cf890>
如果你重载__repr__(),除了调用super(Class, obj).__repr__()和reexing它,有没有任何方法来获得内存地址?
当你在Python中调用object.__repr__()方法时,你会得到类似这样的结果:
< __main__。测试对象位于0x2aba1c0cf890>
如果你重载__repr__(),除了调用super(Class, obj).__repr__()和reexing它,有没有任何方法来获得内存地址?
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))
)
使用ctypes,您可以使用
>>> import ctypes
>>> a = (1,2,3)
>>> ctypes.addressof(a)
3077760748L
文档:
addressof(C实例)->整数 返回C实例内部缓冲区的地址
注意,在CPython中,当前id(a) == ctypes.addressof(a),但是ctypes.addressof(a)。addressof应该返回每个Python实现的真实地址,如果
支持Ctypes 内存指针是一个有效的概念。
编辑:增加关于ctypes的解释器独立性的信息
虽然在默认的CPython实现中,id(object)确实可以获取对象的地址,但这通常是无用的…你不能对纯Python代码中的地址做任何事情。
只有在C扩展库中才能使用该地址……在这种情况下,获取对象的地址是很简单的,因为Python对象总是作为C指针传递。
只是为了响应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()值。
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对象。
我知道这是一个老问题,但如果你现在还在用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>'
你可以使用内置的'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__重载,你可以考虑__str__来查看变量的内存地址。
下面是Moshe Zadka在StackOverflow中__repr__和__str__的细节。