我有这个代码在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
所以你看,父节点和节点(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(),因为它们应该引用同一个节点,但它们不是。
答案 0 :(得分:2)
代码似乎没问题。我看到的唯一“不完美”是特殊情况:
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))
答案 1 :(得分:0)
此答案仅指您需要通过指定名称来引用前一个实例的部分(假设最多有一个节点具有相同的名称)。
我的建议是你试用元类。 我知道这在Python中是一个有争议的问题,但我认为值得了解。 此外,我认为有更好,更pythonic的方式这样做,但尽管如此,这是我的解决方案.. 下一个代码片段可能会起作用。 (没检查!我正在用手机写字。可能需要进行小的调整。)
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)