Python密钥错误 - 用于字典中的密钥:字典[key]

时间:2015-06-14 00:47:33

标签: python dictionary key keyerror

我正在编写一个Graph类来处理游戏中的路径。图有一个字段,即映射,它是将节点映射到边的字典。在我的一个函数中,我有以下代码:

for key in self.mapping:
    connected_edges = self.mapping[key]

在我的程序中的某一点上,我调用此代码并收到以下错误:

KeyError: <node.Node instance at 0x00000000026F3088>

这怎么可能?我只是循环遍历字典中的键,那么键怎么可能不在其中呢?为了理智检查,我拿了字典的长度,看到它是5,即:不是0.任何想法?谢谢!

我为Node和Edge实现了我自己的 eq 哈希方法。以下是课程的这些部分:

class Node:
    """
    A node connects to other nodes via Edges to form a graph

    Each node has a unique identifier (ID) so they can be mathematically distinct. Optionally, a node also has an x and
    y coordinate.
    """
    n_nodes = 0
    def __init__(self, x=0, y=0):
        """
        Create a node with its own unique identifier.

        :param x: x coordinate
        :param y: y coordinate
        :return: an initialized Node object
        """
        Node.n_nodes += 1
        self.ID = Node.n_nodes
        self.x = x  # x position
        self.y = y  # y position

    def __eq__(self, other):
        return (self.ID, self.x, self.y) == (other.ID, other.x, other.y)

    def __hash__(self):
        return hash((self.ID, self.x, self.y))



class Edge:
    """
    An edge is a connection between two nodes.

    Edges have a unique identifier and a list of two nodes. Optionally, an edge can have a numerical weight. Edges can
    also be directed, in which case it is only possible to traverse the edge in one direction, not both.
    """
    n_edges = 0
    def __init__(self, node1, node2, weight=1, directed=False):
        """
        Create an edge with its own unique identifier

        :param node1: node at first end of the edge
        :param node2: node at second end of the edge
        :param weight: numerical weight of the connection between node1 and node2
        :param directed: if True, the edge is oriented from node1 to node 2
        :return: an initialized Edge object
        """
        Edge.n_edges += 1
        self.ID = Edge.n_edges
        self.weight = weight
        self.nodes = frozenset([node1, node2])
        self.directed = directed

    def __eq__(self, other):
        return (self.ID, self.weight, self.nodes, self.directed) == (other.ID, other.weight, other.nodes, other.directed)

    def __hash__(self):
        return hash((self.ID, self.weight, self.nodes, self.directed))

1 个答案:

答案 0 :(得分:2)

如果您的对象实现__eq____hash__,则必须确保在创建对象后哈希值不会更改。如果在创建对象后改变对象,则可以使它们进入不一致状态,即在字典中为它们存储的哈希值与其当前哈希值不一致。这是一个例子:

class Foo(object):
    def __init__(self, x):
        self.x = x
    def __eq__(self, other):
        return self.x == other.x
    def __hash__(self):
        return self.x

a, b, c = Foo(1), Foo(2), Foo(3)

x = {a: 1, b: 2, c: 3}

for key in x:
    print(x[key])

a.x = 100

for key in x:
    print(x[key])

结果是KeyError类似于您收到的KeyError。据推测,你正在改变你的Node对象。

不能对可变对象进行哈希处理(或者至少,它们的哈希值不能取决于它们的任何可变状态)。