How to implement a list of links in python?

I am trying to simulate a collection of objects in python (2). A collection must create a specific attribute (integer, float, or any immutable object) of objects accessible through the list interface.

(1)

>>> print (collection.attrs) [1, 5, 3] >>> collection.attrs = [4, 2, 3] >>> print (object0.attr == 4) True 

I especially expect this list interface in the collection to reassign one attribute of an object, e.g.

(2)

 >>> collection.attrs[2] = 8 >>> print (object2.attr == 8) True 

I am sure that this is a fairly common situation, unfortunately, I could not find a satisfactory answer on how to implement it in stackoverflow / google, etc.

Behind the scenes, I expect object.attr be implemented as a mutable object. Somehow, I also expect the collection to contain a "list of links" for object.attr , and not the links themselves (immutable).

I ask for your suggestion on how to solve this in an elegant and flexible way.

A possible implementation that allows (1), but not for (2),

 class Component(object): """One of many components.""" def __init__(self, attr): self.attr = attr class System(object): """One System object contains and manages many Component instances. System is the main interface to adjusting the components. """ def __init__(self, attr_list): self._components = [] for attr in attr_list: new = Component(attr) self._components.append(new) @property def attrs(self): # !!! this breaks (2): return [component.attr for component in self._components] @attrs.setter def attrs(self, new_attrs): for component, new_attr in zip(self._components, new_attrs): component.attr = new_attr 

The !!! line breaks (2), because we create a new list whose entries refer to the values โ€‹โ€‹of all Component.attr , and not to the links to the attributes themselves.

Thanks for your input.

Thexma

+1
source share
2 answers

Just add another proxy in between:

 class _ListProxy: def __init__(self, system): self._system = system def __getitem__(self, index): return self._system._components[index].attr def __setitem__(self, index, value): self._system._components[index].attr = value class System: ... @property def attrs(self): return _ListProxy(self) 

You can make proxy fancier by doing all the other list methods, but that's enough for your use case.

+2
source

@filmor thanks for your answer, this solves the problem perfectly! I made this a little more general:

 class _ListProxy(object): """Is a list of object attributes. Accessing _ListProxy entries evaluates the object attributes each time it is accessed, ie this list "proxies" the object attributes. """ def __init__(self, list_of_objects, attr_name): """Provide a list of object instances and a name of a commonly shared attribute that should be proxied by this _ListProxy instance. """ self._list_of_objects = list_of_objects self._attr_name = attr_name def __getitem__(self, index): return getattr(self._list_of_objects[index], self._attr_name) def __setitem__(self, index, value): setattr(self._list_of_objects[index], self._attr_name, value) def __repr__(self): return repr(list(self)) def __len__(self): return len(self._list_of_objects) 

Are there any important list methods?

But what if I want some of the components (objects) to be garbage collected? Should I use something like WeakList to prevent memory leak?

0
source

All Articles