206

当您object.__repr__()在 Python 中调用该方法时,您会得到如下信息:

<__main__.Test object at 0x2aba1c0cf890> 

如果您重载,是否有任何方法可以获取内存地址__repr__(),然后调用super(Class, obj).__repr__()和正则表达式?

4

11 回答 11

240

Python手册有这样的说法id()

返回对象的“身份”。这是一个整数(或长整数),保证在其生命周期内对于该对象是唯一且恒定的。具有非重叠生命周期的两个对象可能具有相同的 id() 值。 (实现说明:这是对象的地址。)

所以在 CPython 中,这将是对象的地址。但是,对于任何其他 Python 解释器都没有这样的保证。

请注意,如果您正在编写 C 扩展,您可以完全访问 Python 解释器的内部,包括直接访问对象的地址。

于 2008-09-23T14:41:30.270 回答
82

您可以通过这种方式重新实现默认 repr:

def __repr__(self):
    return '<%s.%s object at %s>' % (
        self.__class__.__module__,
        self.__class__.__name__,
        hex(id(self))
    )
于 2008-09-23T14:49:57.553 回答
62

只需使用

id(object)
于 2008-09-23T14:37:24.853 回答
29

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

首先,id只返回:

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


在 CPython 中,这恰好是指向PyObject在解释器中表示对象的指针,这与object.__repr__显示的内容相同。但这只是 CPython 的一个实现细节,而不是 Python 的一般情况。Jython 不处理指针,它处理 Java 引用(JVM 当然可能将其表示为指针,但是您看不到这些,也不想看到,因为允许 GC 移动它们)。PyPy 允许不同类型有不同种类的id,但最通用的只是您调用的对象表的索引idon,这显然不是一个指针。我不确定 IronPython,但我怀疑在这方面它更像 Jython 而不是 CPython。因此,在大多数 Python 实现中,没有办法得到其中显示的任何内容repr,如果这样做也没有用。


但是如果你只关心 CPython 怎么办?毕竟,这是一个很常见的情况。

好吧,首先,您可能会注意到这id是一个整数;* 如果您想要该0x2aba1c0cf890字符串而不是数字46978822895760,您将不得不自己格式化它。在幕后,我相信object.__repr__最终会使用printf's%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的 C 级的地址。int32c_int32

话虽如此,通常情况下,如果您真的认为需要某物的地址,那么您一开始就不需要原生 Python 对象,而是需要一个ctypes对象。

于 2014-10-09T18:41:51.540 回答
14

只是为了回应 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
于 2011-01-07T17:14:04.557 回答
4

使用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 的解释器独立性的信息

于 2008-09-23T15:00:58.150 回答
3

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

id(self)
于 2008-09-23T14:38:01.760 回答
2

我知道这是一个老问题,但如果你还在编程,这些天在 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>'
于 2019-09-25T22:53:26.233 回答
1

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

这是一个使用它来获取对象的内存地址的示例:

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
>>>

在这里,我使用带有对象/项目(例如作为参数)的内置object“类”方法来返回字符串,然后我对该字符串进行分区,该字符串将在我返回的字符串之前返回字符串的元组提供,我提供的字符串,然后是我提供的字符串之后的字符串,并且由于内存位置位于' '之后,我可以获得内存地址,因为它已将其与该部分进行了分区。__repr__1object at

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

于 2021-08-06T16:34:37.970 回答
0

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

您真正能够使用该地址的唯一时间是来自 C 扩展库......在这种情况下,获取对象的地址是微不足道的,因为 Python 对象总是作为 C 指针传递。

于 2008-09-23T16:10:37.110 回答
0

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

这是StackOverflow 中Moshe Zadka的__repr__vs__str__的详细信息。

于 2021-10-04T19:19:56.350 回答