改变内置容器检查相等性方式的唯一途径是让它们包含作为值,而不是“原始”,包装值(包装在覆盖__eq__的类中和__ne__)。这是如果您需要更改容器本身使用相等检查的方式,例如出于in 运算符的目的,其中右侧操作数是一个列表——以及在容器的方法中,例如它们自己的__eq__(type(x).__eq__(y) 是 Python 在内部执行您编码的典型方式如x == y)。
如果您所说的是执行您自己的平等检查(没有改变容器本身内部执行的检查),那么唯一的方法就是改变每个 cont1 == cont2 到(例如)same(cont1, cont2, value_same) 其中value_same 是一个接受两个值并返回True 或False 的函数,就像== 一样。按照您指定的标准,这可能过于侵入性 WRT。
如果您可以更改容器本身(即,创建容器对象的位置数量远小于检查两个容器是否相等的位置数量),那么使用容器覆盖__eq__ 的子类是最好的。
例如:
class EqMixin(object):
def __eq__(self, other):
return same(cont1, cont2, value_same)
(same 就像我在 A 的第二段中提到的那样)和
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)自己不能强>被改变。这是一个非常不同的哲学,例如Ruby 和 Javascript(我个人更喜欢它,但我确实看到它有时会受到限制!)。
编辑:对于各种容器类型,OP 的特定请求似乎是(就这个答案而言)“我如何实现 same”,而不是如何在不更改 @ 的情况下应用它987654345@ 进入函数调用。如果这是正确的,那么(例如)为了简单起见不使用迭代器:
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,根据要求,NOT 到 keys。 “模糊化”字典的键(或集合的成员)的相等比较是一个 REAL 问题。这么看:第一,你如何保证samevalue(a, b) and samevalue(b, c)完全暗示和保证samevalue(a, c)?这种传递性条件不适用于我见过的大多数半明智的“模糊比较”,但对于基于哈希表的容器(例如字典和集合)来说,它是完全不可缺少的。如果你通过了这个障碍,那么让哈希值以某种方式“神奇地”一致的噩梦就会出现——如果一个字典中的两个实际不同的键在这个意义上“映射到”相等性与 相同键入另一个字典,然后应该使用两个对应值中的哪一个......?如果你问我,这种方式很疯狂,所以我希望当你说 values 时,你确实是指,values 和 >不是键!-)