Se puede aplicar por sí mismo, de manera similar a cómo se ha hecho, pero con una subclase lista que llama a flush() antes de intentar acceder a un elemento.
Obviamente, no desea hacer esto en cada acceso, pero puede optimizar esto configurando una devolución de llamada en la referencia débil para marcar la lista como sucia cuando algo muere. Entonces solo necesita vaciar la lista cuando algo ha muerto desde el último acceso.
Aquí hay una clase de lista implementada con este método. (Tenga en cuenta que no se prueba mucho, y algunos métodos no se implementan de manera muy eficiente (por ejemplo, aquellos que simplemente se convierten a una lista real y llaman al método), pero debería ser un punto de partida razonable:
import weakref
class WeakList(list):
def __init__(self, seq=()):
list.__init__(self)
self._refs = []
self._dirty=False
for x in seq: self.append(x)
def _mark_dirty(self, wref):
self._dirty = True
def flush(self):
self._refs = [x for x in self._refs if x() is not None]
self._dirty=False
def __getitem__(self, idx):
if self._dirty: self.flush()
return self._refs[idx]()
def __iter__(self):
for ref in self._refs:
obj = ref()
if obj is not None: yield obj
def __repr__(self):
return "WeakList(%r)" % list(self)
def __len__(self):
if self._dirty: self.flush()
return len(self._refs)
def __setitem__(self, idx, obj):
if isinstance(idx, slice):
self._refs[idx] = [weakref.ref(obj, self._mark_dirty) for x in obj]
else:
self._refs[idx] = weakref.ref(obj, self._mark_dirty)
def __delitem__(self, idx):
del self._refs[idx]
def append(self, obj):
self._refs.append(weakref.ref(obj, self._mark_dirty))
def count(self, obj):
return list(self).count(obj)
def extend(self, items):
for x in items: self.append(x)
def index(self, obj):
return list(self).index(obj)
def insert(self, idx, obj):
self._refs.insert(idx, weakref.ref(obj, self._mark_dirty))
def pop(self, idx):
if self._dirty: self.flush()
obj=self._refs[idx]()
del self._refs[idx]
return obj
def remove(self, obj):
if self._dirty: self.flush() # Ensure all valid.
for i, x in enumerate(self):
if x == obj:
del self[i]
def reverse(self):
self._refs.reverse()
def sort(self, cmp=None, key=None, reverse=False):
if self._dirty: self.flush()
if key is not None:
key = lambda x,key=key: key(x())
else:
key = apply
self._refs.sort(cmp=cmp, key=key, reverse=reverse)
def __add__(self, other):
l = WeakList(self)
l.extend(other)
return l
def __iadd__(self, other):
self.extend(other)
return self
def __contains__(self, obj):
return obj in list(self)
def __mul__(self, n):
return WeakList(list(self)*n)
def __imul__(self, n):
self._refs *= n
return self
[Editar] Agregar una aplicación lista más completa
¿podría por favor defina "morir", "referencia", "flush", "eliminación manual"? esta pregunta realmente no tiene mucho sentido sin esos. – hop
dado = la referencia débil se vuelve inválida ("muerta"). referencia = una referencia débil (http://docs.python.org/library/weakref.html). flush = eliminación manual = iterar sobre todas las referencias en la lista eliminando aquellas que no son válidas. – Dan
todavía no es muy claro, a menos que ya sepa qué hacer – hop