gpt4 book ai didi

python - python中的弱引用列表

转载 作者:IT老高 更新时间:2023-10-28 21:12:53 26 4
gpt4 key购买 nike

我需要一个弱引用列表,以便在项目死亡时删除它们。目前我这样做的唯一方法是继续刷新列表(手动删除死引用)。

我知道有 WeakKeyDictionary 和 WeakValueDictionary,但我真的很喜欢 WeakList,有没有办法做到这一点?

这是一个例子:

import weakref

class A(object):
def __init__(self):
pass

class B(object):
def __init__(self):
self._references = []

def addReference(self, obj):
self._references.append(weakref.ref(obj))

def flush(self):
toRemove = []

for ref in self._references:
if ref() is None:
toRemove.append(ref)

for item in toRemove:
self._references.remove(item)

b = B()

a1 = A()
b.addReference(a1)
a2 = A()
b.addReference(a2)

del a1
b.flush()
del a2
b.flush()

最佳答案

您可以自己实现它,与您的做法类似,但使用一个在尝试访问项目之前调用 flush() 的列表子类。

显然,您不想在每次访问时都这样做,但您可以通过在弱引用上设置回调来优化此操作,以便在某些东西死亡时将列表标记为脏。然后,您只需要在自上次访问后发生某些事情时刷新列表。

这是一个使用此方法实现的列表类。 (请注意,它没有经过太多测试,并且某些方法的实现效率不是很高(例如,那些只是转换为真实列表并在其上调用方法的方法),但这应该是一个合理的起点:

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

关于python - python中的弱引用列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/677978/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com