I am a bit puzzled right now about the following:
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)'
Why does repr(proxy_a)
return a representation of the proxy while proxy_a.__repr__()
returns the representation of the original object? Shouldn't the two calls boil down to the same thing? And which __repr__
implementation is actually called by using repr(proxy_a)
?
repr(proxy_a)
calls the default C implementation of repr
for the weakref.proxy
object. While proxy_a.__repr__()
proxies the version from the a
object.
Yes I would expect them to execute the same code, but wait, don't we expect also the proxy to send attribute lookups and method calls to the proxied object? At the same time I would want to see that a proxy is a proxy object, so the repr(proxy_a)
result makes sense too. So it is not even clear what should be the right behaviour.
Information on this is very scarce, but it looks weakref.proxy
objects do not replace in a complete transparent way the original objects, contrary to common expectations.
Added a few print lines to make things more clear. Note in the last line, that it is possible to access the weakreferred object and its methods through the __self__
parameter of a bound method from the 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)'
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)
See also this complete thread python-dereferencing-weakproxy and some of the entries in this (old) thread from the Python bugtracker, where weakref.proxy
and method delegation is mentioned in several places.