改变内置容器检查相等性的方式的唯一途径是使它们包含为值,而不是“原始值”,wrapped值(包装在覆盖的类中__eq__
and __ne__
)。如果您需要改变容器本身使用相等性检查的方式,例如为了目的in
右侧操作数是列表的运算符——以及容器的方法,例如它们自己的方法__eq__
(type(x).__eq__(y)
是 Python 在内部执行代码的典型方式x == y
).
如果你说的是表演your own平等检查(without改变容器本身内部执行的检查),那么唯一的方法就是改变每个cont1 == cont2
进入(例如)same(cont1, cont2, value_same)
where value_same
是一个接受两个值并返回的函数True
or False
like ==
会。根据您指定的标准,这可能过于侵入性 WRT。
如果你能改变容器本身(即,创建容器对象的位置数量远小于检查两个容器是否相等的位置数量),然后使用覆盖的容器子类__eq__
是最好的。
E.g.:
class EqMixin(object):
def __eq__(self, other):
return same(cont1, cont2, value_same)
(with same
正如我在 A 的第二段中提到的)
class EqM_list(EqMixin, list): pass
(对于您需要的其他容器类型,依此类推),然后无论您有什么地方(例如)
x = list(someiter)
将其更改为
x = EqM_list(someiter)
并且一定要掌握其他创建列表对象的方法,例如代替
x = [bah*2 for bah in buh]
with
x = EqM_list(bah*2 for bah in buh)
and
x = d.keys()
with
x = EqM_list(d.iterkeys())
等等。
是的,我知道,这很麻烦——但这是 Python 的核心原则(和实践;-),内置类型(无论是容器,还是值类型,例如float
) 他们自己cannot被改变。这是一种与例如非常不同的哲学。 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, 按照要求,NOT to keys。 “模糊”字典的键(或集合的成员)的相等比较是REAL问题。这样看:首先,你如何绝对确定的保证 that samevalue(a, b) and samevalue(b, c)
完全暗示并确保samevalue(a, c)
?这种传递性条件不适用于我见过的大多数半明智的“模糊比较”,但对于基于哈希表的容器(例如字典和集合)来说它是完全不可或缺的。如果你克服了这个障碍,那么让散列值以某种方式“神奇地”一致的噩梦就会出现——如果一个字典中的两个实际上不同的键在这种意义上“映射到”相等性,会怎么样?the samekey 在另一个字典中,那么应该使用两个相应值中的哪一个......?这就是疯狂所在,如果你问我,所以我希望当你说values you do确切地说,意思是values, and not keys!-)