在我的代码中,对各种容器(列表,字典等)的相等性进行了大量的比较 . 容器的键和值的类型为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 回答
改变内置容器检查相等性的唯一途径是使它们包含值而不是"originals"包装值(包含在覆盖
__eq__
和__ne__
的类中) . 如果您需要更改容器本身使用相等性检查的方式,例如出于in
运算符的目的,其中右侧操作数是一个列表 - 以及容器的方法,例如它们自己的__eq__
(type(x).__eq__(y)
是Python在内部执行的典型方式,您编码为x == y
) .如果你在谈论正在执行 your own 平等检查(但不改变容器本身内部执行的检查)什么,那么唯一的办法就是改变每
cont1 == cont2
成(例如)same(cont1, cont2, value_same)
其中value_same
是一个函数接受两个值并返回True
或False
喜欢==
会 . 这可能是太具侵略性的WRT你指定的标准 .如果你可以改变 the container themselves (即,创建容器对象的位置数远远小于检查两个容器是否相等的位置数),那么使用覆盖
__eq__
的容器子类是最好的 .例如 . :
(正如我在A的第2段中提到的那样
same
)和(等等您需要的其他容器类型),然后在任何地方(例如)
改成它
并确保还捕获其他方法来创建列表对象,例如更换
同
和
同
等等 .
是的,我知道,这是多么麻烦 - 但这是Python的核心原则(和实践;-)内置类型(无论是容器,还是像
float
这样的值类型)本身 cannot 都要改变 . 那's a very different philosophy from e.g. Ruby'和Javascript(我个人更喜欢它,但我确实看到它有时看起来有限!) .Edit :OP特定请求似乎是(就这个答案而言)“我如何为各种容器类型实现
same
”,而不是如何在不将==
更改为函数调用的情况下应用它 . 如果这是正确的,那么(例如)不使用迭代器以简化:请注意,这适用于 values ,根据要求, NOT 至 keys . "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 时,你的意思是,确切地说, values 和 not 键! - )