ZODB 3中的PersistentSet
ZODB 提供了一个叫 PersistentList
的东西和一个叫 PersistentMapping
的东西,但我想要一个 PersistentSet
。于是我写了一个简单的类,模仿了 ZODB 2 里的古老 PersistentList
。因为 Python 里没有 UserSet
,所以我只能从 C 语言写的内置 set
继承。
class PersistentSet(UserSet, Persistent):
def __iand__(self, other):
set.__iand__(other)
self._p_changed = 1
...
...
...
def symmetric_difference_update(self, other):
set.symmetric_difference_update(other)
self._p_changed = 1
结果代码出现了一个“多个基类有实例布局冲突”的 错误。我尝试在 set
周围创建一个 UserSet
的包装,但这也没解决问题。
class UserSet(set):
def __init__(self):
self.value = set
def __getattribute__(self, name):
return self.value.__getattribute__(name
最后,我导入了 sets.Set
(这个已经被内置的 set
替代了),但看起来这个也是用 C 实现的。我在 PyPI 上没有找到任何集合的实现,所以现在我陷入了困境。
我还有哪些选择呢? 我可能需要从头开始实现一个集合,或者使用 UserDict
,然后把所有的 value
都扔掉。
3 个回答
1
为了将来阅读,我想提供一个对已经提出的答案的小改进...
自定义持久集合类
class PersistentSet(Persistent):
def __init__(self, *args, **kwargs):
self._set = set(*args, **kwargs)
def __getattr__(self, name):
return getattr(self._set, name)
库中的持久集合类
from BTrees.OOBTree import OOSet
另见
1
将所有属性请求转发到内部设置:
class PersistentSet(Persistent):
def __init__(self):
self.inner_set = set()
def __getattribute__(self, name):
try:
inner_set = Persistent.__getattribute__(self, "inner_set")
output = getattr(inner_set, name)
except AttributeError:
output = Persistent.__getattribute__(self, name)
return output
3
为什么不使用ZODB中提供的持久集合类呢?在这里有四个这样的类。IITreeSet和IOTreeSet用来管理整数集合,而OITreeSet和OOTreeSet则用来管理任意对象的集合。它们分别对应四个BTree类:IIBTree、IOBTree、OIBTree和OOBTree。相比于Python内置的集合实现,这些类的优势在于它们有更快的查找机制(这要归功于底层的BTree)以及持久化支持。
下面是一些示例代码:
>>> from BTrees.IIBTree import IITreeSet, union, intersection
>>> a = IITreeSet([1,2,3])
>>> a
<BTrees._IIBTree.IITreeSet object at 0x00B3FF18>
>>> b = IITreeSet([4,3,2])
>>> list(a)
[1, 2, 3]
>>> list(b)
[2, 3, 4]
>>> union(a,b)
IISet([1, 2, 3, 4])
>>> intersection(a,b)
IISet([2, 3])