简体   繁体   English

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

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

I had a question about dictionaries with custom objects.我对带有自定义对象的字典有疑问。 In a dict, I know that the key has to be immutable, so if I want to use a custom class, I have to define its hash function.在字典中,我知道密钥必须是不可变的,所以如果我想使用自定义 class,我必须定义它的 hash function。 The hash doc in python recommends you use the hash function on the tuple of the equal dunder method. python 中的 hash 文档建议您使用 hash ZC1C4under25268E683894D1AB507Ztuple7 上的方法。 So for example, i defined the custom class temp as such:例如,我定义了自定义 class 温度,如下所示:

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

This way I can have they key:value pair such as temp(1):1.这样我就可以拥有它们的键:值对,例如 temp(1):1。 So to my question.所以我的问题。 In python, you can have different types in the same dict.在 python 中,您可以在同一个字典中有不同的类型。 So I declared this dict:所以我宣布了这个字典:

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

The problem I am facing is that I would get an error for the int:int and bool:int pairing telling me the error:我面临的问题是我会收到一个错误 int:int 和 bool:int 配对告诉我错误:

'bool' object has no attribute 'value' “布尔” object 没有属性“值”

or或者

'int' object has no attribute 'value' 'int' object 没有属性 'value'

Can someone explain to me why this is the case?有人可以向我解释为什么会这样吗? The same issue would happen if I have a different class in the dict as well.如果我在字典中有不同的 class 也会发生同样的问题。 So an object from a cars class would give this error:因此,来自汽车 class 的 object 会给出此错误:

'cars' object has no attribute 'value' “汽车” object 没有属性“值”

Strangely enough in my tests, I found that if the key is a tuple or a float, it works fine.奇怪的是,在我的测试中,我发现如果键是元组或浮点数,它就可以正常工作。 Any help would be greatly appreciated.任何帮助将不胜感激。 I wanted to know why the error is happening and how I can fix it.我想知道为什么会发生错误以及如何修复它。 MY main goal is to learn how to my one dict that has various objects from different classes.我的主要目标是学习如何使用我的一个包含来自不同类的各种对象的字典。

Your eq method needs to check if the other object is the same type:您的 eq 方法需要检查其他 object 是否为同一类型:

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

That said, I highly recommend using dataclasses for cases like this.也就是说,我强烈建议在这种情况下使用数据类 They define init, eq, and (if frozen=True ) hash for you, which helps avoid this sort of issue.他们为您定义了 init、eq 和(如果 freeze frozen=True ) hash,这有助于避免此类问题。

The issue happens when running the __eq__ and __lt__ dunder methods.运行__eq____lt__ dunder 方法时会出现此问题。 You can reproduce the same by running:您可以通过运行来重现相同的内容:

temp(1) == 1

The issue happens because __eq__ receives other as 1, and the value 1 does not have a .value , but you're trying to use it here:出现问题是因为__eq__接收other作为 1,并且值 1 没有.value ,但您尝试在此处使用它:

return self.value == other.value

If you just use other for comparisons it should work:如果您只是使用 other 进行比较,它应该可以工作:

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

You can define your __eq__ method like this:你可以像这样定义你的__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.奇怪的是,在我的测试中,我发现如果键是元组或浮点数,它就可以正常工作。

As for the second question, this has got to do with how a dict works.至于第二个问题,这与dict的工作方式有关。 For every key, the instance of dict checks if the hash of the key exists.对于每个键, dict的实例检查该键的 hash 是否存在。 If yes, then it checks for equality with other keys with the same hash.如果是,则它检查与具有相同 hash 的其他键是否相等。 Here, the check for equality is to check if they are basically the same keys (and hence the same hash).在这里,相等性检查是检查它们是否基本上是相同的键(因此是相同的哈希)。 If the equality check fails, then the keys are deemed different.如果相等检查失败,则认为密钥不同。

If there are no hash collisions, then no equality checks are done.如果没有 hash 冲突,则不进行相等检查。 Hence, when you used a tuple as a key, say, (1, 2) , its hash((1, 2)) = 3713081631934410656 , which doesn't yet exist in the dict .因此,当您使用tuple作为键时,例如(1, 2) ,其hash((1, 2)) = 3713081631934410656尚不存在于dict中。 Hence no error.因此没有错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM