访问对象存储器地址

时间:2020-03-06 14:36:10  来源:igfitidea点击:

当我们在Python中调用object .__ repr __()方法时,我们会得到类似以下的信息:

<main.Test object at 0x2aba1c0cf890>

如果重载__repr __(),然后调用super(Class,obj).__ repr __()并将其重新赋值,还有什么方法可以保留内存地址?

解决方案

只需使用

id(object)

我们可以通过以下方式获得适合该目的的东西:

id(self)

Python手册中有关于id()的说法:

Return the ``identity'' of an object.
  This is an integer (or long integer)
  which is guaranteed to be unique and
  constant for this object during its
  lifetime. Two objects with
  non-overlapping lifetimes may have the
  same id() value. (Implementation note:
  this is the address of the object.)

因此,在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 instance) -> integer

  Return the address of the C instance internal buffer

注意在CPython中,当前id(a)== ctypes.addressof(a),但是ctypes.addressof应该返回每个Python实现的真实地址,如果

  • 支持ctypes
  • 内存指针是一个有效的概念。

编辑:添加了有关ctypes解释器独立性的信息

虽然id(object)在默认的CPython实现中获取对象的地址是正确的,但这通常是无用的……我们不能对纯Python代码中的地址做任何事情。

实际上,唯一可以使用该地址的时间是来自C扩展库...在这种情况下,获取对象的地址很简单,因为Python对象始终作为C指针传递。