Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between weakref.proxy and weakref.ref?

From the documentation:

Weakref.proxy returns a proxy to object which uses a weak reference. But if I run the following code:

obj = SomeObj()
obj  # <__main__.ExpensiveObject at 0xbfc5390>
p = weakref.proxy(obj)
r = weakref.ref(obj)

r() # <__main__.ExpensiveObject at 0xbfc5390>
# the weakreference gives me the same object as expected
p  # <__main__.ExpensiveObject at 0xc456098>
# the proxy refers to a different object, why is that?

Any help will be really appreciated! Thanks!

like image 704
Bubble Bubble Bubble Gut Avatar asked Sep 08 '25 11:09

Bubble Bubble Bubble Gut


2 Answers

You're using IPython, which has its own pretty-printing facilities. The default pretty-printer prefers to inspect the object's class through __class__ instead of type:

def _default_pprint(obj, p, cycle):
    """
    The default print function.  Used if an object does not provide one and
    it's none of the builtin objects.
    """
    klass = _safe_getattr(obj, '__class__', None) or type(obj)
    if _safe_getattr(klass, '__repr__', None) is not object.__repr__:
        # A user-provided repr. Find newlines and replace them with p.break_()
        _repr_pprint(obj, p, cycle)
        return
    p.begin_group(1, '<')
    p.pretty(klass)
    ...

but weakref.proxy objects lie about their class through __class__, so the pretty-printer thinks the proxy really is an instance of ExpensiveObject. It doesn't see the proxy's __repr__, and it prints the class as ExpensiveObject instead of weakproxy.

like image 85
user2357112 supports Monica Avatar answered Sep 10 '25 03:09

user2357112 supports Monica


Something is odd, as I can't reproduce your issue:

>>> import weakref
>>> class Foo: pass
... 
>>> f = Foo()
>>> f
<__main__.Foo object at 0x7f40c44f63c8>
>>> p = weakref.proxy(f)
>>> p
<weakproxy at 0x7f40c44f9a98 to Foo at 0x7f40c44f63c8>
>>> r = weakref.ref(f)
>>> r
<weakref at 0x7f40c4502278; to 'Foo' at 0x7f40c44f63c8>
>>> r()
<__main__.Foo object at 0x7f40c44f63c8>

This code has been entered at a fresh interpreter instance. The output is very different from yours! Which version of python are you using?

like image 41
nosklo Avatar answered Sep 10 '25 05:09

nosklo