dict.keys()中的dict键和键之间有什么区别?

and*_*fun 3 python dictionary key python-2.7

我最近遇到了python 2.7的问题:

class A(object):
    def __init__(self, v):
        self.v = v

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

a1 = A(1)
a2 = A(1)
Run Code Online (Sandbox Code Playgroud)

所以:

print a1 == a2  # True
Run Code Online (Sandbox Code Playgroud)

和:

d = {a1: 1}
print a2 in d.keys()  # True
Run Code Online (Sandbox Code Playgroud)

但:

print a2 in d  # False
Run Code Online (Sandbox Code Playgroud)

问题是a2 ind.keys()和之间的主要区别是什么a2 in d?我该怎么a2 in d is True办?

the*_*eye 7

在Python 2.7中,dict.keys返回一个键列表,并将a2 in d.keys()线性迭代所有键,以查找是否a2在列表中.

但是,a2 in d只需a2在字典中根据对象的哈希值进行O(1)查找,以查看密钥a2是否在d.


但在你的情况下,问题完全不同.引用官方文档,

如果一个类没有定义一个__cmp__()或一个__eq__()方法,它也不应该定义一个__hash__()操作; 如果它定义__cmp__()__eq__()不定义__hash__(),它的实例将不能在散列集合中使用.如果一个类定义了可变对象并实现了一个__cmp__()__eq__()方法,那么它就不应该实现__hash__(),因为hashable集合实现要求对象的散列值是不可变的(如果对象的散列值改变,它将在错误的散列桶中).

既然你没有明确定义__hash__的功能,你破坏了他们之间的合同,并__hash__使用基于默认的散列id的对象,这将是两个不同的a1a2.因此,即使a1并且a2相似,散列对象也会将它们视为两个不同的对象,因为它们的散列值不同.

要解决这个问题,你需要定义__hash__函数,就像这样

class A(object):

    def __init__(self, v):
        self.v = v

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

    def __hash__(self):
        return hash(self.v)

a1 = A(1)
a2 = A(1)

d = {a1: 1}
print a2 in d.keys()  # True
print a2 in d         # True
Run Code Online (Sandbox Code Playgroud)