【问题标题】:Method to compare Python dictionaries fails with certain value types?比较 Python 字典的方法因某些值类型而失败?
【发布时间】:2012-11-08 01:39:34
【问题描述】:

我想不通。我有两个相同的字典。我使用标准方法来确定差异,应该没有差异。但是某些值类型总是作为差异返回,即使它们不是。例如,如果一个值为pymongo.bson.ObjectId,则该方法无法将其评估为相同。

d1 = {'Name':'foo','ref1':ObjectId('502e232ca7919d27990001e4')}

d2 = {'Name':'foo','ref1':ObjectId('502e232ca7919d27990001e4')}

d1 == d2

返回:

True

但是:

set((k,d1[k]) for k in set(d1) & set(d2) if d1[k] != d2[k])

返回:

set([('ref1',Objectid('502e232ca7919d27990001e4'))])

所以我发现这很奇怪,不是吗?

d1['ref1'] == d2['ref1']  # True

d1['ref1'] != d2['ref1']  # False

什么?????!?!??!!?

【问题讨论】:

  • 您的两个ObjectId 值是对同一个对象的引用,还是它们是不同的对象? ObjectId 类是否适当地实现了 __eq__?我试图用一个虚拟的ObjectId 重现,但我得到了预期的结果(一个空集)。
  • 这是一个很好的问题,因为根据the docs,“映射(字典)比较相等当且仅当它们的排序(键,值)列表比较相等。”所以d1 == d2 应该暗示d1[k] == d2[k]
  • ObjectId 可能是一个错误的类,其中hash(o) 是基于例如o.value,但o1==o2 不是。但如果相等和散列都不是基于值的,这是完全合理的行为。
  • @Blckknght 相同的对象。 __eq__ 结帐,但id 不结帐
  • 谢谢大家,对所有的红鲱鱼感到抱歉。它是一个错误jira.mongodb.org/browse/PYTHON-440

标签: python dictionary set


【解决方案1】:

ObjectId('502e232ca7919d27990001e4') 创建一个新对象,默认情况下!= 比较引用。举个例子:

class Obj:
    def __init__(self, value):
        self.value = value

print Obj(1234) == Obj(1234) # False

这将评估为 false,因为它们是不同的实例,即使它们具有相同的值。为了使这项工作,该类必须实现 eq 方法:

class Obj:
    def __init__(self, value):
        self.value = value

    def __eq__(self, other):
        return self.value == other.value

print Obj(1234) == Obj(1234) # True

要解决此问题,您可以“猴子补丁”类:

class Obj:
    def __init__(self, value):
        self.value = value

print Obj(1234) == Obj(1234) # False

Obj.__eq__ = lambda a, b: a.value == b.value

print Obj(1234) == Obj(1234) # True

或者直接比较它们的值。

print Obj(1234).value == Obj(1234).value

尽可能比较这些值,因为猴子补丁可能会破坏看似无关的代码。

【讨论】:

  • 在这种情况下,您绝对应该添加一个__hash__ 方法来保证相等的对象返回相同的值,例如def __hash__(self): return hash(self.value),以防止问题中的行为发生。跨度>
  • 谢谢,你让我进入了测试模式,帮助我找到了错误
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多