1

背景

PDBBiopython 的模块中,PDB 结构被解析为Structure对象,这些对象将结构的组件存储在 SMCRA 架构中(Structure/Model/Chain/Residue/Atom)。此层次结构的每一级都由一个继承Entity容器类的对象表示。

等价

我的问题是任何两个实体对象都不能相等。

从同一个文件构建的结构不相等:

>>> from Bio import PDB
>>> parser = PDB.PDBParser()
>>> struct1 = parser.get_structure("1hgg", "pdb1hgg.ent")
>>> struct2 = parser.get_structure("1hgg", "pdb1hgg.ent")
>>> struct1 == struct2
False

该结构中的残基不相等:

>>> first_res1 = struct1.get_residues().next()
>>> first_res2 = struct2.get_residues().next()
>>> first_res1 == first_res2
False

等等。

如果我们要分别解析同一个 PDB 文件,则结构中的任何Entity对象都不可能相等。

解决方案

这个问题的明显解决方案是永远不要对同一个 PDB 文件进行两次解析。然后,我们有对象身份,因此,等价。但是,这个答案对我来说似乎不完整。

每个Entity对象都可以返回一个标识元组get_full_id()。此方法给出从顶部对象向下的所有 id;如果在构造对象时提供了正确的 PDB id,则它对于结构中的每个结构都应该是唯一的Entity,并且在所有结构中都是唯一的。Structure

我测试Entity等效性的解决方案只是比较这个完整的 id。那是:

def __eq__(self, other):
    return self.get_full_id() == other.get_full_id()

问题

在这一点上,我在问我对Entity等价的实现是否明智。

  • 误报(例如,提供相同 PDB id 的不同结构)是否令人担忧?
  • 每当我们需要测试等效性时,简单地手动比较完整的 id 会更好吗?
  • 是否有任何理由在模块__eq__中未实现?PDB
4

1 回答 1

1

不定义 an 的一个常见原因__eq__是它使事物不可散列(因此您不能将它们用作字典键或将它们放在集合中),除非您还定义了一致的__hash__函数,并且您的对象是不可变的。

默认情况下__hash__,对象只使用 ID,这甚至适用于可变对象,因为 ID 永远不会改变。但是如果你定义了一个 custom __eq__,你就不能继续按 ID 进行散列,否则你会遇到两个对象可以比较相等但具有不同散列的情况,这与散列的工作方式不一致。所以你必须定义一个自定义__hash__函数(你可以这样做),但是如果你的对象是可变的,你也不能/不应该真的这样做所以你只会有一个不可散列的对象。这对你来说可能没问题。

在此处的 python 文档中查看更多信息。

__eq__因此,只要您不需要对象是可散列的,或者它们是不可变的,您就可以使用自定义;否则事情会变得更复杂。或者您可以不理会__eq__,将您的完整 ID 比较函数命名为其他名称,以免破坏哈希性。

我不太了解 PDB ID 的含义(特别是是否可能出现误报),无法__eq__从这个角度判断您的实施是否合理。

于 2012-05-29T15:46:56.770 回答