我的代码看起来像这样:
class SomeClass(str):
pass
some_dict = {'s':42}
>>> type(some_dict.keys()[0])
str
>>> s = SomeClass('s')
>>> some_dict[s] = 40
>>> some_dict # expected: Two different keys-value pairs
{'s': 40}
>>> type(some_dict.keys()[0])
str
为什么Python将对象s
转换为字符串" s"在更新字典some_dict
?
答案 0 :(得分:17)
虽然哈希值是相关的,但它不是主要因素。
在这里,平等更为重要。也就是说,对象可能具有相同的哈希值并且不相等,但是相等的对象必须具有相同的哈希值(尽管这不是严格执行的)。否则,在使用dict
和set
时,您会遇到一些奇怪的错误。
由于您尚未在__eq__
上定义SomeClass
方法,因此您继承了str
上的__eq__
方法。 Python的内置构建是为了允许子类化,所以's' == SomeClass('s')
返回true,如果对象本来是相同的,那么它们不具有不同的类型。例如。 's'
是真的。因此,SomeClass('s')
和__eq__
等同于字典的键是正确和恰当的。
要获得所需的行为,您必须重新定义__hash__
dunder方法以考虑类型。但是,当您定义自定义等号时,python会停止为您提供自动str.__hash__
dunder方法,您也必须重新定义它。但在这种情况下,我们可以重用class SomeClass(str):
def __eq__(self, other):
return (
type(self) is SomeClass
and type(other) is SomeClass
and super().__eq__(other)
)
__hash__ = str.__hash__
d = {'s': 1}
d[SomeClass('s')] = 2
assert len(d) == 2
print(d)
。
{'s': 2, 's': 1}
打印:@"C\\"":([.0-9]*),"
答案 1 :(得分:0)
这是一个非常好的问题。首先,当把(key,value)对放入dict
时,它使用哈希函数来获取密钥的哈希值,并检查是否存在该哈希码。如果存在,则dict
将对象与相同的哈希码进行比较。如果两个对象相等(__eq__(self, other)
返回True
),则会更新该值,这就是您的代码遇到此类行为的原因。
鉴于SomeClass
甚至未被修改,因此's'
和SomeClass('s')
应具有相同的哈希码,'s'.__eq__(SomeClass('s'))
将返回True。