【问题标题】:PersistentSet in ZODB 3ZODB 3 中的持久集
【发布时间】:2009-05-17 22:07:09
【问题描述】:

ZODB 提供PersistentListPersistentMapping,但我想要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

代码产生了“多个基础存在实例布局冲突”error。我尝试在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 上找到任何 set 实现,所以我现在处于死胡同。

我有什么选择?我可能不得不从头开始实施一个集合,或者使用 UserDict 并丢弃所有的 values。

【问题讨论】:

    标签: python set zodb


    【解决方案1】:

    为什么不使用 ZODB 中 BTree 库提供的持久集类。有 4 个这样的类可用。 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])
    

    【讨论】:

      【解决方案2】:

      将所有属性请求转发到内部集合:

      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
      

      【讨论】:

      • 您的解决方案有效,但我做了一些更改。我将 *args 添加到构造函数中,并在 try 块的末尾添加了 self._p_changed=1 ......我不确定这是否是不必要的,或者是否在响应中意外省略了它。谢谢。
      • @Nikhil,这是一个简单的捷径。您只需假设每个变量访问都会更改数据。如果你想让它完美,只需用 self._p_changed = 1 包装每个更改集合的方法
      【解决方案3】:

      对于未来的阅读,我只是想对已经提出的答案稍作改进......

      自定义持久集类

      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
      

      另见

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-26
        • 2017-06-16
        • 1970-01-01
        相关资源
        最近更新 更多