Using weak references

Another alternative (if we don't want to use __dict__) is to make the descriptor object keep track of the values for each instance itself, in an internal mapping, and return values from this mapping as well.

There is a caveat, though. This mapping cannot just be any dictionary. Since the client class has a reference to the descriptor, and now the descriptor will keep references to the objects that use it, this will create circular dependencies, and, as a result, these objects will never be garbage-collected because they are pointing at each other.

In order to address this, the dictionary has to be a weak key one, as defined in the weakref (WEAKREF 01) module.

In this case, the code for the descriptor might look like the following:

from weakref import WeakKeyDictionary


class DescriptorClass:
def __init__(self, initial_value):
self.value = initial_value
self.mapping = WeakKeyDictionary()

def __get__(self, instance, owner):
if instance is None:
return self
return self.mapping.get(instance, self.value)

def __set__(self, instance, value):
self.mapping[instance] = value

This addresses the issues, but it does come with some considerations:

  • The objects no longer hold their attributes—the descriptor does instead. This is somewhat controversial, and it might not be entirely accurate from a conceptual point of view. If we forget this detail, we might be asking the object by inspecting its dictionary, trying to find things that just aren't there (calling vars(client) will not return the complete data, for example).
  • It poses the requirement over the objects that they need to be hashable. If they aren't, they can't be part of the mapping. This might be too demanding a requirement for some applications.

For these reasons, we prefer the implementation that has been shown so far in this book, which uses the dictionary of each instance. However, for completeness, we have shown this alternative as well.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.128.170.27