22

我一直在尝试创建一个dict继承自UserDict.DictMixin支持非哈希键的子类。性能不是问题。不幸的是,PythonDictMixin通过尝试从子类创建一个 dict 对象来实现其中的一些功能。我可以自己实现这些,但我被困在__cmp__.

我找不到__cmp__dict 类的内置逻辑的简洁描述。

4

3 回答 3

33

如果您要问比较字典的工作原理,那就是:

  • 要比较字典 A 和 B,首先比较它们的长度。如果它们不相等,则返回 cmp(len(A), len(B))。
  • 接下来,找到 A 中的键 adiff,它是 的最小键adiff not in B or A[adiff] != B[adiff]。(如果没有这样的键,则字典是相等的。)
  • 还找到 B 中的最小键 bdiff bdiff not in A or A[bdiff] != B[bdiff]
  • 如果 adiff != bdiff,则返回 cmp(adiff, bdiff)。否则返回 cmp(A[adiff], B[bdiff])。

在伪代码中:

def smallest_diff_key(A, B):
    """return the smallest key adiff in A such that adiff not in B or A[adiff] != B[bdiff]"""
    diff_keys = [k for k in A if k not in B or A[k] != B[k]]
    return min(diff_keys)

def dict_cmp(A, B):
    if len(A) != len(B):
        return cmp(len(A), len(B))
    try:
        adiff = smallest_diff_key(A, B)
    except ValueError:
        # No difference.
        return 0
    bdiff = smallest_diff_key(B, A)
    if adiff != bdiff:
        return cmp(adiff, bdiff)
    return cmp(A[adiff], b[bdiff])

这是从 dictobject.c 中的 2.6.3 实现翻译而来的。

于 2010-08-14T17:49:19.610 回答
2

另一种方法是使用集合包中的 Mapping ABC。它在 2.6 及更高版本中可用。您只需从 collections.Mapping 继承并实现__getitem____contains____iter__方法。您可以免费获得其他一切。

于 2010-08-14T17:48:27.033 回答
0

__cmp__ 这里有一个描述,但我认为需要注意的重要一点是,__cmp__它仅在“丰富的比较”方法(例如__lt____eq__未定义)时使用。此外,在 Python3 中,__cmp__已从语言中删除。所以也许__cmp__完全避开,只定义__lt__and __eq__

于 2010-08-14T17:43:41.990 回答