如何在 Python 中的一个字典中包含来自不同 类 的不同对象?

How to have different objects from different classes in one dict in Python?

我对带有自定义对象的字典有疑问。在字典中,我知道键必须是不可变的,所以如果我想使用自定义 class,我必须定义它的哈希函数。 python 中的哈希文档建议您在 equal dunder 方法的元组上使用哈希函数。因此,例如,我定义了自定义 class temp:

class temp():
    def __init__(self,value):
        self.value = value
    def __hash__(self):
        return hash(self.value)
    def __eq__(self,other):
        return self.value == other.value
    def __lt__(self,other):
        return self.value < other.value

这样我就可以得到它们 key:value 对,例如 temp(1):1。所以我的问题。在 python 中,你可以在同一个字典中有不同的类型。所以我声明了这个字典:

myDict={ temp(1):1, temp(2):2, 'a':1,1:1, (1,2):1, True:1 }

我面临的问题是 int:int 和 bool:int 配对出现错误,告诉我错误:

'bool'对象没有属性'value'

'int'对象没有属性'value'

有人可以向我解释为什么会这样吗?如果我在字典中也有不同的 class ,也会发生同样的问题。因此来自汽车 class 的对象会给出此错误:

'cars'对象没有属性'value'

奇怪的是,在我的测试中,我发现如果键是元组或浮点数,它工作正常。 任何帮助将不胜感激。我想知道为什么会发生错误以及如何解决它。我的主要目标是学习如何使用我的字典,其中包含来自不同 classes 的各种对象。

您的 eq 方法需要检查另一个对象是否为同一类型:

def __eq__(self,other):
    if not isinstance(other, temp):
        return NotImplemented
    return self.value==other.value

也就是说,我强烈建议在这种情况下使用 dataclasses。他们为您定义了 init、eq 和 (if frozen=True) hash,这有助于避免此类问题。

问题发生在 运行 __eq____lt__ dunder 方法时。您可以通过 运行:

重现相同内容
temp(1) == 1

出现此问题是因为 __eq__other 接收为 1,而值 1 没有 .value,但您尝试在此处使用它:

return self.value == other.value

如果您只是使用其他进行比较,它应该有效:

class temp():
    def __init__(self,value):
        self.value = value
    def __hash__(self):
        return hash(self.value)
    def __eq__(self,other):
        return self.value == other
    def __lt__(self,other):
        return self.value < other

您可以这样定义 __eq__ 方法:

def __eq__(self, other):
    if other is None:
        return False

    if self.__class__ != other.__class__:
        return False

    return self.value == other.value

Strangely enough in my tests, I found that if the key is a tuple or a float, it works fine.

至于第二个问题,这与dict的工作原理有关。 对于每个键,dict 的实例检查键的哈希值是否存在。如果是,则它检查与具有相同散列的其他键是否相等。在这里,相等性检查是检查它们是否基本上是相同的键(因此是相同的散列)。如果相等性检查失败,则认为键不同。

如果没有散列冲突,则不进行相等性检查。因此,当您使用 tuple 作为键时,例如 (1, 2),它的 hash((1, 2)) = 3713081631934410656dict 中尚不存在。因此没有错误。