首页 文章

内置容器的自定义比较

提问于
浏览
5

在我的代码中,对各种容器(列表,字典等)的相等性进行了大量的比较 . 容器的键和值的类型为float,bool,int和str . 内置的==和!=工作得非常好 .

我刚刚了解到必须使用自定义比较函数来比较容器值中使用的浮点数 . 我已经编写了这个函数(让我们称它为approxEqual(),并假设它需要两个浮点数,如果它们被判断为相等则返回True,否则返回False) .

我更喜欢将现有代码的更改保持在最低限度 . (新的类/函数/等可以根据需要复杂化 . )

例:

if dict1 != dict2:
  raise DataMismatch

需要重写 dict1 != dict2 条件,以便使用approxEqual函数而不是 __eq__ 来比较dict1和dict2的值中使用的任何浮点数 .

字典的实际内容来自各种来源(解析文件,计算等) .

注意:我asked a question earlier关于如何覆盖内置float的 eq . 这本来是一个简单的解决方案,但我了解到Python没有't allow overriding built-in types' __eq__ 运算符 . 因此这个新问题 .

1 回答

  • 9

    改变内置容器检查相等性的唯一途径是使它们包含值而不是"originals"包装值(包含在覆盖 __eq____ne__ 的类中) . 如果您需要更改容器本身使用相等性检查的方式,例如出于 in 运算符的目的,其中右侧操作数是一个列表 - 以及容器的方法,例如它们自己的 __eq__type(x).__eq__(y) 是Python在内部执行的典型方式,您编码为 x == y ) .

    如果你在谈论正在执行 your own 平等检查(但不改变容器本身内部执行的检查)什么,那么唯一的办法就是改变每 cont1 == cont2 成(例如) same(cont1, cont2, value_same) 其中 value_same 是一个函数接受两个值并返回 TrueFalse 喜欢 == 会 . 这可能是太具侵略性的WRT你指定的标准 .

    如果你可以改变 the container themselves (即,创建容器对象的位置数远远小于检查两个容器是否相等的位置数),那么使用覆盖 __eq__ 的容器子类是最好的 .

    例如 . :

    class EqMixin(object):
      def __eq__(self, other):
        return same(cont1, cont2, value_same)
    

    (正如我在A的第2段中提到的那样 same )和

    class EqM_list(EqMixin, list): pass
    

    (等等您需要的其他容器类型),然后在任何地方(例如)

    x = list(someiter)
    

    改成它

    x = EqM_list(someiter)
    

    并确保还捕获其他方法来创建列表对象,例如更换

    x = [bah*2 for bah in buh]
    

    x = EqM_list(bah*2 for bah in buh)
    

    x = d.keys()
    

    x = EqM_list(d.iterkeys())
    

    等等 .

    是的,我知道,这是多么麻烦 - 但这是Python的核心原则(和实践;-)内置类型(无论是容器,还是像 float 这样的值类型)本身 cannot 都要改变 . 那's a very different philosophy from e.g. Ruby'和Javascript(我个人更喜欢它,但我确实看到它有时看起来有限!) .

    Edit :OP特定请求似乎是(就这个答案而言)“我如何为各种容器类型实现 same ”,而不是如何在不将 == 更改为函数调用的情况下应用它 . 如果这是正确的,那么(例如)不使用迭代器以简化:

    def samelist(a, b, samevalue):
        if len(a) != len(b): return False
        return all(samevalue(x, y) for x, y in zip(a, b))
    
    def samedict(a, b, samevalue):
        if set(a) != set(b): return False
        return all(samevalue(a[x], b[x]) for x in a))
    

    请注意,这适用于 values ,根据要求, NOTkeys . "Fuzzying up" dict 's keys (or a set'成员的相等比较)是一个真正的问题 . 以这种方式看待它:首先,如何 samevalue(a, b) and samevalue(b, c) samevalue(a, b) and samevalue(b, c) 完全暗示并确保 samevalue(a, c) ?这种传递性条件不适用于对于基于散列表的容器(例如dicts和sets)完全不可或缺的大多数半敏感性条件 . 如果你通过那个障碍,那么制造哈希值的噩梦就会出现 - 如果两个实际上不同的键在这个意义上与另一个词中的 the same 键相等,那两个相应的值应该是什么然后用......?这种方式疯狂,如果你问我,所以我希望当你说 values 时,你的意思是,确切地说, valuesnot 键! - )

相关问题