通过参考访问的对象字典

时间:2016-04-09 16:54:25

标签: python python-3.x

我正在尝试在Python中创建一个二叉树,其中每个节点都有一个关联的元组(a, b)。我只想创建一次节点对象,当我随后访问它们时,我想访问先前创建的节点对象(因为我想修改它们中的一些变量)。

目前,我正在使用节点对象的字典,以及用于创建节点的“工厂方法”。我从不打电话给Node(a, b);如果需要,工厂方法可以。代码是

existing_nodes = {}

class Node:
    def __init__(self, a, b):
        # stuff
        existing_nodes.update([((a, b), self)])

def get_node(a, b):
    return existing_nodes.get((a, b), Node(a, b))

但是当我在其余代码的多个位置尝试get_node(0, 0)时,它会给我不同的对象。如果我在一个引用中修改变量,则它不会显示在其他引用中。另外,如果我print,则会显示不同的地址。

出了什么问题?如何为节点对象创建引用字典?

1 个答案:

答案 0 :(得分:2)

首先创建一个Node()实例,只有然后测试字典中的(a, b)元组。 Python解析你的表达式:

existing_nodes.get((a, b), Node(a, b))
像这样:

t = (a, b)
n = Node(a, b)
existing_nodes.get(t, n)

(但未指定tn),但调用Node(a, b)会将self添加到同一字典中。这样,每次调用工厂函数时都会替换上一个节点。

不要从Node.__init__向字典添加节点。请改用dict.setdefault();如果找不到密钥,它会为你添加默认字典:

class Node:
    def __init__(self, a, b):
        # stuff

def get_node(a, b):
    return existing_nodes.setdefault((a, b), Node(a, b))

这仍然会每次创建一个新的Node(),但只有在缺少元组时才会返回它。您可以通过首先测试密钥来完全避免这种情况:

def get_node(a, b):
    if (a, b) not in existing_nodes:
        existing_nodes[a, b] = Node(a, b)
    return existing_nodes[a, b]

您可以从Node.__new__函数执行此操作,而不必使用工厂函数:

class Node(object):
    _existing_nodes = {}

    def __new__(cls, a, b):
        if (a, b) not in cls._existing_nodes:
            cls._existing_nodes[a, b] = super(Node, cls).__new__(cls, a, b)
        return cls._existing_nodes[a, b]

    def __init__(self, a, b):
        # stuff