Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x Python:自定义可变类可以用作字典的键吗?_Python 3.x_Hashmap_Hashtable_Immutability - Fatal编程技术网

Python 3.x Python:自定义可变类可以用作字典的键吗?

Python 3.x Python:自定义可变类可以用作字典的键吗?,python-3.x,hashmap,hashtable,immutability,Python 3.x,Hashmap,Hashtable,Immutability,假设我们有这样一个自定义节点类: class Node: def __init__(self, val, next, random): self.val = val self.next = next self.random = random 我有一个节点对象,想用作字典的键。 我的理解是,一个对象应该是不可变的和可散列的,这样它才能可靠地用作字典键,因为一个可变对象可能会导致散列值发生变化,而这个对象是可变的 我知道python确实允许自

假设我们有这样一个自定义节点类:

class Node:
    def __init__(self, val, next, random):
        self.val = val
        self.next = next
        self.random = random
我有一个节点对象,想用作字典的键。
我的理解是,一个对象应该是不可变的和可散列的,这样它才能可靠地用作字典键,因为一个可变对象可能会导致散列值发生变化,而这个对象是可变的

我知道python确实允许自定义可变对象用作字典键,这是如何工作的

更新:引用的链接不涉及自定义对象的易变性方面。它们只是提供了一种方法来覆盖哈希函数的默认实现。此问题应重新打开,因为它与引用的“重复”问题不同


答案:自定义可变对象使用的哈希方法的默认实现,该方法在对象的生命周期内保证唯一且恒定。可变自定义对象不应覆盖哈希函数的默认实现。下面提供了更详细的答案

节点自定义对象根据其类定义是可变的,任何可变对象都不应覆盖默认方法使用的哈希方法的默认实现,因为默认方法保证在对象的生命周期内是唯一和恒定的。这样做可能会导致对象的哈希值发生更改,并可能导致许多问题

例如:

Node node = new Node(5, None, None)
cache = {}
cache[node] = "Node added"
node.val = 5

# If we override default implementation of hash function, we have to
# make sure hashing function does not use object attributes else
# accessing cache[node] now would cause problem as a different hashed 
# value would be computed and we won't be able to retrieve "Node added" 
# value. 

# Default implementation uses identity and would always hash 
# to same value even if the object mutates.
但是我们可以继续并重写不可变对象的哈希方法。线程上的答案帮助我理解了它是如何工作的。对于以下内容,我们将假设一旦对象被创建,节点对象的属性将永远不会改变。

这里的想法是确保自定义对象实现哈希和相等方法

相等方法的实现方式应确保两个逻辑等价对象始终被视为相等。对于给定的节点对象,如果两个节点的所有属性都相同,则认为它们相等。因此,我们可以构建一个键,它是所有属性的元组。这是因为元组是不可变的,所以我们基本上创建了一个包含对象所有属性的不可变对象,并将使用它来计算散列

下面的实现确保两个逻辑上等价的节点(具有相同的属性)具有相同的密钥,因此将为两个相等的节点生成相同的哈希值

class Node:
    def __init__(self, val, next, random):
        self.val = val
        self.next = next
        self.random = random

    def __key(self):
        return (self.val, self.next, self.random)

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

    def __eq__(self, other):
        if isinstance(other, Node):
            return self.__key() == other.__key()
        return NotImplemented

它部分回答了我的问题,因为它采用了一个非常具体的示例,其中类只有一个“str”类型的属性,该属性是不可变的。我将回答这个问题,因为我知道了一个具有多个属性的类对象如何被用作字典的键,即使它的属性是可变的。@Anatolii的可能副本我担心这个问题将不得不打开,因为引用链接不是我问题的准确答案。可以吗?当然可以,但是,在你的问题中,你应该解释为什么这些链接不是正确的答案。否则,你将得不到足够的选票(除了我之外)重新开始这个问题。我当时投票决定重新开始你的问题。