Tôi đã tự hỏi liệu có một cách dễ dàng để xây dựng một bộ đặt hàng có thể lập chỉ mục yếu trong Python hay không. Tôi đã cố gắng xây dựng một bản thân. Dưới đây là những gì tôi đã đưa ra:Cài đặt có thể lập chỉ mục yếu có thể lập chỉ mục trong Python
"""
An indexable, ordered set of objects, which are held by weak reference.
"""
from nose.tools import *
import blist
import weakref
class WeakOrderedSet(blist.weaksortedset):
"""
A blist.weaksortedset whose key is the insertion order.
"""
def __init__(self, iterable=()):
self.insertion_order = weakref.WeakKeyDictionary() # value_type to int
self.last_key = 0
super().__init__(key=self.insertion_order.__getitem__)
for item in iterable:
self.add(item)
def __delitem__(self, index):
values = super().__getitem__(index)
super().__delitem__(index)
if not isinstance(index, slice):
# values is just one element
values = [values]
for value in values:
if value not in self:
del self.insertion_order[value]
def add(self, value):
# Choose a key so that value is on the end.
if value not in self.insertion_order:
key = self.last_key
self.last_key += 1
self.insertion_order[value] = key
super().add(value)
def discard(self, value):
super().discard(value)
if value not in self:
del self.insertion_order[value]
def remove(self, value):
super().remove(value)
if value not in self:
del self.insertion_order[value]
def pop(self, *args, **kwargs):
value = super().pop(*args, **kwargs)
if value not in self:
del self.insertion_order[value]
def clear(self):
super().clear()
self.insertion_order.clear()
def update(self, *args):
for arg in args:
for item in arg:
self.add(item)
if __name__ == '__main__':
class Dummy:
def __init__(self, value):
self.value = value
x = [Dummy(i) for i in range(10)]
w = WeakOrderedSet(reversed(x))
del w[2:8]
assert_equals([9,8,1,0], [i.value for i in w])
del w[0]
assert_equals([8,1,0], [i.value for i in w])
del x
assert_equals([], [i.value for i in w])
Có cách nào dễ dàng hơn để thực hiện việc này không?
Rất đẹp! Thành phần 'data' của' weakref.WeakSet' được viết ở đâu? –
Các tài liệu cho WeakSet chưa hoàn thành (hầu như không tồn tại). –
Pypy sử dụng cùng một (hoặc rất tương tự) 'WeakSet' thực hiện, do đó, điều này làm việc ở đó là tốt (' gc.collect() 'là cần thiết để xóa weakrefs). – simonzack