Per una collezione di essere a conoscenza di mutazione dei suoi elementi, ci deve essere un collegamento tra gli elementi e che la raccolta in grado di comunicare quando cambiamenti accadere. Per questo motivo, è necessario associare un'istanza a una raccolta o proxy degli elementi della raccolta in modo che la comunicazione delle modifiche non si diffonda nel codice dell'elemento.
Una nota sull'implementazione che ho intenzione di presentare, il metodo di proxy funziona solo se gli attributi sono modificati dall'impostazione diretta, non all'interno di un metodo. Sarebbe quindi necessario un sistema di contabilità più complesso.
Inoltre, si presume che non esisteranno esatto duplicato di tutti gli attributi, dato che si richiedono gli indici essere costruiti fuori set
oggetti invece di list
from collections import defaultdict
class Proxy(object):
def __init__(self, proxy, collection):
self._proxy = proxy
self._collection = collection
def __getattribute__(self, name):
if name in ("_proxy", "_collection"):
return object.__getattribute__(self, name)
else:
proxy = self._proxy
return getattr(proxy, name)
def __setattr__(self, name, value):
if name in ("_proxy", "collection"):
object.__setattr__(self, name, value)
else:
proxied = self._proxy
collection = self._collection
old = getattr(proxied, name)
setattr(proxy, name, value)
collection.signal_change(proxied, name, old, value)
class IndexedCollection(object):
def __init__(self, items, index_names):
self.items = list(items)
self.index_names = set(index_names)
self.indices = defaultdict(lambda: defaultdict(set))
def __len__(self):
return len(self.items)
def __iter__(self):
for i in range(len(self)):
yield self[i]
def remove(self, obj):
self.items.remove(obj)
self._remove_from_indices(obj)
def __getitem__(self, i):
# Ensure consumers get a proxy, not a raw object
return Proxy(self.items[i], self)
def append(self, obj):
self.items.append(obj)
self._add_to_indices(obj)
def _add_to_indices(self, obj):
for indx in self.index_names:
key = getattr(obj, indx)
self.indices[indx][key].add(obj)
def _remove_from_indices(self, obj):
for indx in self.index_names:
key = getattr(obj, indx)
self.indices[indx][key].remove(obj)
def signal_change(self, obj, indx, old, new):
if indx not in self.index_names:
return
# Tell the container to update its indices for a
# particular attribute and object
self.indices[indx][old].remove(obj)
self.indices[indx][new].add(obj)
Perché si creare dizionari di '' e '' quando l'oggetto ha già sia gli attributi? –
Desidero gli indici per l'accesso rapido, ad esempio voglio ottenere oggetto di stato 3 –
Cosa succede se più oggetti hanno lo stato o il timestamp simile? –