Thane Brimhall
Thane Brimhall

Reputation: 9555

A more efficient way to use a weakref on an object as a property?

I know in Python I can do something like the following:

from weakref import ref

class A(object):
    def __init__(self, parent):
        self._parent = ref(parent)

    @property
    def parent(self):
        return self._parent()

a = A(some_other_object)
print a.parent

In this hypothetical situation, I create an instance of A and access the weakly-referenced parent object in a nice way. It seems like 4 lines of code per weakly-referenced property is a bit much, though.

I thought I could do something like the following as a shortcut to the above:

class A(object):
    def __init__(self, parent):
        self.parent = property(ref(parent))

but this doesn't return the parent object, it returns a property object. Is there a more compact way to create a weakly-referenced object I can access as a property rather than a callable?

Upvotes: 4

Views: 989

Answers (2)

Tomasz Łazarowicz
Tomasz Łazarowicz

Reputation: 435

I use weakref.proxy for this.

import weakref

class A(object):
    def __init__(self, parent)
        self.parent = weakref.proxy(parent)

Upvotes: 4

BrenBarn
BrenBarn

Reputation: 251408

You can make it a little more compact, but not as compact as you seem to want. The problem is there are two incompatible needs:

  1. The assignment of _parent must be inside the body of a method (e.g., __init__) because it has to be set on the instance.
  2. The creation of the property cannot be inside the body of a method, because properties only work when defined on the class.

An additional complication is that there is no way to do parent = somePropertyMaker(ref(x)) and have the somePropertyMaker function "know" that it is being assigned to the name "parent". That means you will have to explicitly pass the name of the hidden attribute underlying the property.

With that in mind you can do this:

def weakProp(hidden):
    @property
    def prop(self):
        return getattr(self, hidden)()
    return prop

class A(object):
    def __init__(self, parent):
        self._parent = ref(parent)

    parent = weakProp('_parent')

class B(object):
    pass

>>> b = B()
>>> a = A(b)
>>> print b
<__main__.B object at 0x00000000029D0470>
>>> print a.parent
<__main__.B object at 0x00000000029D0470>

The weakProp is a property-maker function that retrieves the hidden attribute and calls it to access the weakly-referenced object.

Upvotes: 0

Related Questions