在哪里可以找到 __repr__ of Python weakref 代理?

Where to find __repr__ of Python weakref proxy?

我现在对以下问题有点困惑:

import weakref

class A:
    def __init__(self, p):
        self.p = p
        
    def __repr__(self):
        return f"{type(self).__name__}(p={self.p!r})"
    
a = A(1)
proxy_a = weakref.proxy(a)

print(repr(proxy_a))
# '<weakproxy at 0x7f2ea2fc1b80 to A at 0x7f2ea2fee610>'
print(proxy_a.__repr__())
# 'A(p=1)'

为什么 repr(proxy_a) return 是代理的表示,而 proxy_a.__repr__() return 是原始对象的表示?这两个电话不应该归结为同一件事吗?哪个 __repr__ 实现实际上是通过使用 repr(proxy_a)?

调用的

repr(proxy_a)weakref.proxy 对象调用 repr 的默认 C 实现。 proxy_a.__repr__() 代理来自 a 对象的版本。

是的,我希望它们执行相同的代码,但是等等,难道我们不希望代理向被代理对象发送属性查找和方法调用吗?同时我希望看到代理是代理对象,所以 repr(proxy_a) 结果也有意义。所以甚至不清楚什么是正确的行为。

这方面的信息非常稀少,但看起来 weakref.proxy 对象并没有以完全透明的方式替换原始对象,这与普遍预​​期相反。

添加了一些打印行以使内容更加清晰。请注意最后一行,可以通过代理的绑定方法的 __self__ 参数访问弱引用对象及其方法。

import weakref

class A:
    def __init__(self, p):
        self.__p = p
        
    def __repr__(self):
        return f"{type(self).__name__}(p={self.__p!r})"

a = A(1)
proxy_a = weakref.proxy(a)

print(repr(proxy_a))
# '<weakproxy at 0x7f2ea2fc1b80 to A at 0x7f2ea2fee610>'
print(proxy_a.__repr__())
# 'A(p=1)'
print(proxy_a.__repr__)
# <bound method A.__repr__ of A(p=1)>
print(type(proxy_a))
# <class 'weakproxy'>
print(type(proxy_a.__repr__.__self__))
# <class '__main__.A'>
print(proxy_a.__repr__.__self__.__repr__())
# A(p=1)

另请参阅 Python bugtracker 中的完整线程 python-dereferencing-weakproxy and some of the entries in this (old) thread,其中 weakref.proxy 和方法委托在多处提到​​。