【问题标题】:custom comparison for built-in containers内置容器的自定义比较
【发布时间】:2010-10-04 23:55:28
【问题描述】:

在我的代码中,对各种容器(列表、字典等)的相等性进行了大量比较。容器的键和值是 float、bool、int 和 str 类型。内置的 == 和 != 运行良好。

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

我希望将对现有代码的更改保持在最低限度。 (新的类/函数/等可以根据需要变得复杂。)

例子:

if dict1 != dict2:
  raise DataMismatch

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

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

注意:我asked a question earlier 关于如何覆盖内置浮点的eq。那将是一个简单的解决方案,但我了解到 Python 不允许覆盖内置类型的 __eq__ 运算符。因此提出了这个新问题。

【问题讨论】:

  • 您的问题是什么?如果你已经有了这个功能,那有什么问题?
  • 您能否提供一些您希望以不同方式工作的示例代码?

标签: python comparison


【解决方案1】:

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

如果您所说的是执行您自己的平等检查(没有改变容器本身内部执行的检查),那么唯一的方法就是改变每个 cont1 == cont2 到(例如)same(cont1, cont2, value_same) 其中value_same 是一个接受两个值并返回TrueFalse 的函数,就像== 一样。按照您指定的标准,这可能过于侵入性 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,根据要求,NOTkeys。 “模糊化”字典的键(或集合的成员)的相等比较是一个 REAL 问题。这么看:第一,你如何保证samevalue(a, b) and samevalue(b, c)完全暗示和保证samevalue(a, c)?这种传递性条件不适用于我见过的大多数半明智的“模糊比较”,但对于基于哈希表的容器(例如字典和集合)来说,它是完全不可缺少的。如果你通过了这个障碍,那么让哈希值以某种方式“神奇地”一致的噩梦就会出现——如果一个字典中的两个实际不同的键在这个意义上“映射到”相等性与 相同键入另一个字典,然后应该使用两个对应值中的哪一个......?如果你问我,这种方式很疯狂,所以我希望当你说 values 时,你确实是指,values >不是键!-)

【讨论】:

  • 是的,我的意思是值而不是键.. 更正问题:)
  • 是的,我没有想到你提到的键的问题;仔细一想,我才意识到,这就像你说的那样是一场灾难。幸运的是,没有人使用浮点数作为键(或者换句话说,没有人发疯),所以一切都很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-20
  • 2018-12-22
  • 2021-03-17
相关资源
最近更新 更多