Reputation: 9555
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
Reputation: 435
I use weakref.proxy for this.
import weakref
class A(object):
def __init__(self, parent)
self.parent = weakref.proxy(parent)
Upvotes: 4
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:
_parent
must be inside the body of a method (e.g., __init__
) because it has to be set on the instance.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