【问题标题】:When PersistentDict, when Folder?什么时候PersistentDict,什么时候文件夹?
【发布时间】:2012-02-29 16:02:17
【问题描述】:

什么时候应该使用 PersistentDict,什么时候应该使用 Folder?它们在更新、内部结构、性能等方面有什么区别?

【问题讨论】:

    标签: python zodb repoze.bfg


    【解决方案1】:

    PersistentMapping 只是 python dict 类型的实现(通过标准库 UserDict 基类),针对 ZODB 的持久性语义进行了调整;每次更改 mapping 时,它都不必在继承自 Persistent 的最近类上设置 _p_changed 标志。

    Folder 是一个更丰富的类型,实现事件,与 Zope Web 界面 (ZMI) 集成,通过 Web 任意属性(带有类型验证的属性),Zope 权限管理,子项验证ids、导入/导出等。子项目文件夹作为属性存储在对象本身上,一些元数据存储在实例的私有字典中。

    当您需要任何这些额外服务(授权、ID 验证等)时,请使用 Folder,否则请使用 PersistentMapping。在性能方面查找或存储项目不会有太大差异;一个是下面的直pythondict,另一个是存储项目的实例__dict__

    如果您正在寻找避免冲突,您应该查看BTreesOOBTree 类基本上是一个持久映射,其中值存储在持久存储桶中,在大多数情况下避免冲突,并为其余部分提供冲突解决方案.

    如果您想要Folder 语义和BTree 存储语义,请查看Products.BTreeFolder2,以及实现Folder 接口但将子对象存储在OOBTree 中而不是直接作为属性的附加组件实例。

    【讨论】:

      【解决方案2】:

      PersistentDict(现在称为PersistentMapping)是一个继承自UserDict.IterableUserDictpersistent.Persistent的类em>。

      UserDict.IterableUserDict 是一个内置的 python 类,它模拟一个可迭代的字典,persistent.Persistent 是一个 Zope 类,它可以将自身的实例保存在ZODB。

      所以 PersistentDict(或 PersistentMapping)基本上是一个字典,可以作为对象存储在 ZODB 中。

      普通字典不能作为单独的对象存储在 ZODB 中。它们必须是从 persistent.Persistent 继承的某个类的属性。

      PersistentDict 将其键和值存储在实际字典中(data 属性)。

      PersistentDict 不能通过 ZMI 添加,我认为它主要用于您希望将字典直接存储在 zodb 中的特殊情况。

      文件夹我猜你的意思是 zope.container.folder 中的文件夹。 Folder 将其子项存储在 OOBTree 对象中,该对象是一个可以容纳大量对象的容器。

      如果您想要一个包含其他内容类型实例的容器,那么您应该使用文件夹。

      文件夹具有 PersistentDict 没有的接口,并且某些适配器或其他组件可能需要这些接口才能工作。例如,ContainerModified 事件只会在文件夹被修改时触发,而不是 PersistentDict。如果您将 PersistentDict 用作​​通用文件夹,则可能会有各种类似的陷阱。

      在性能方面,字典通常会更快,直到键空间变得非常大。然后天平向 OOBTree 倾斜。

      【讨论】:

      • 我可以在没有ConflictErrors的情况下同时修改PersistentDict的不同键吗?假设我有d={'a': [1, 2, 3], 'b': [5, 6, 7]},它们是PersistentDictPersistentList 实例。如果一个线程/进程执行d['a'].append(5),另一个执行del d['b'][2],并且他们都提交......那会是ConflictError吗? Folder 怎么样? (我要自己尝试一下,但首先还有其他事情要做,所以我想我不妨问问。)
      • 忘掉任何关于“文件夹”的概念——您需要将 PersistentDict 与 OOBTree 进行比较(将苹果与苹果进行比较,而不是与水果沙拉进行比较)。在许多情况下,OOBTree 应该具有出色的冲突解决能力,但是对于小型映射,IIRC 可能在同一个存储桶中有两个键,从而消除了这一优势。随着映射变得更大——尤其是如果您使用一种好的策略将插入的键均匀分布在存储桶中,我认为您可以最大限度地减少冲突的可能性。
      • 我的看法:只使用 BTrees(可能是您的示例中的 OOBTree)用于除琐碎或小型映射之外的所有映射,并意识到 keys() 返回的迭代器可以是移动目标,并且更像 iterkeys () - 这违反了 dicts 在 Python 2 中的工作方式,并且在行为上更接近 Python 3 中的 keys() (字典视图与迭代器语义除外)。
      • @sdupton:啊,BTree,太棒了,我认为这是我需要研究的。谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-18
      • 2011-09-28
      • 2012-08-07
      • 2012-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多