繁体   English   中英

Python树实现-节点参考

[英]Python tree implementation - node reference

我有这段代码可以在Python中实现一棵树。 功能之一是查找下面所有节点(包括自身)的值之和,但这不起作用。

我认为原因是因为一旦创建了一个节点,便无法返回并使用Node(名称,值)访问它-这将创建具有该名称和值的新节点,而不是在节点中引用该节点。具有该名称和值的树,并具有与其链接的子级。

因此,sum_below函数仅返回节点的值。 我如何引用树中的节点:

class Node(object):
    def __init__(self, name, value):
        self.name = name
        self.value = value
        self.children = []

    def add_child(self, obj):
        self.children.append(obj)

    def sum_below(self):
        if self.children == []:
            return self.value
        else:
            ret = self.value
            for child in self.children:
                ret += child.sum_below()
            return ret
    def __str__(self, level = 0):
        ret = "\t"*level+repr(self.value)+"\n"
        for child in self.children:
            ret += child.__str__(level+1)
        return ret

[编辑]我的问题是,一旦创建节点,我将无法引用它:

#In [2]:

Node(1,100)
parent = Node(1,100)
child = Node(2, 200)
parent.add_child(child)

#In [5]:

print parent

#Out [5]:

100
    200

#In [6]:

print Node(1,100)

#Out [6]:

100

因此,您可以看到,parent和Node(1,100)没有引用相同的内容。

[编辑]

#In [5]:
parent.sum_below()
#Out[5]:
300
#In [6]:
Node(1,100).sum_below()
#Out[6]:
100

在上面的代码中,Node(1,100).sum_below()应该等于parent.sum_below(),因为它们应该引用相同的节点,但不是。

该代码似乎还可以。 我看到的唯一“不完美”之处是特殊情况:

if self.children == []: ...

根本不需要。 简化版:

def sum_below(self):
    ret = self.value
    for child in self.children:
        ret += child.sum_below()
    return ret

也会工作。 也可以通过使用sum进一步简化:

def sum_below(self):
    return (self.value +
            sum(child.sum_below() for child in self.children))

为什么您没有与parent.sum_below()和Node(1,100).sum_below()获得相同的输出的问题是,“父”是Node类的对象,并且具有一个子属性,该子属性包含另一个节点对象“子”,因此它按应有的方式工作,但是当您编写Node(1,100).sum_below()时,您将创建一个新的对象,其名称属性= 1且值属性= 100并在其上调用sub_below()方法,因此它将返回本身的价值,因为尚未添加任何子项。

而且,您以后甚至无法访问此新创建的节点,因为您没有将其分配给任何变量。 为此,您应该执行以下操作:

 >>>parent2 = Node(1, 100)
 >>>parent2.sum_below()
 100
 >>>parent2.add_child(parent1)
 >>>parent2.sum_below()
 400

该答案仅涉及您需要通过指定名称来引用先前实例的部分(假设最多有一个具有相同名称的节点)。

我的建议是您尝试使用元类。 我知道这在Python中是一个有争议的问题,但我认为值得了解。 另外,我认为有一种更好且更Python化的方法可以执行此操作,但尽管如此,这是我的解决方案。下一个代码段可能会起作用。 (未选中!我正在用手机写信。可能需要进行一些小的调整)。

Class Metanode(object):
    __nodes = {}

def __new__(cls,name,val):
    if name not in Metanode.__nodes.keys():
        Metanode.__nodes[name] = object.__new__(cls,name,val)
    return Metanode.__nodes[name]

然后将其添加为元类:

class Node(metaclass=Metanode,object):
    ''' put rest of your def here '''
    pass

现在,您的元类拥有一个实例字典。 每当您创建名称为“ x”的新实例时,您都会获得使用该名称命名的最后一个实例。 当然,您还需要在元类中处理这些实例的销毁(因此字典中将不包含不存在的实例的键)。

编辑 :在我的计算机中正确检查代码后,此代码无法正常工作。 但是,下面的代码完全不涉及元类,可以工作(在我的Ubuntu机器上使用python3检查):

class Node(object):
    nodes={}

    def new_init(self,name,val):
        self.name = name
        self.val = val
        self.children = [ ]

    def __new__(cls,name,val,*args,**kwds):
        if name not in Node.nodes.keys():
            Node.nodes[name] = super(Node,cls).__new__(cls,*args,**kwds)
            Node.nodes[name].new_init(name,val)
        return Node.nodes[name]

    def __init__(self,name,val):
        pass

    def sum_below(self):
        return self.val + sum(child.sum_below() for child in self.children)

    def add_child(self,node):
        if not isinstance(node,Node):
            '''raise-some-exception-or-whatnot'''
        self.children.append(node)

暂无
暂无

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

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