我尝试在Python中实现树数据结构。这就是我到目前为止的结果:
class Node:
"""
This class implements a node in a tree.
# Arguments #
metadata:dict=dict() | A dict to store metadata.
subnodes:tuple=tuple() | A tuple to define subnodes.
"""
def __init__(self, metadata={"label": None, "content": None, "description": None}, subnodes=list()):
self.metadata = metadata
self.subnodes = subnodes
def __str__(self):
return "[{label}] {content}".format(
label=str(self["label"]),
content=str(self["content"])
)
def __repr__(self):
return "<{}>".format(str(self))
def __len__(self):
count = len(self.subnodes)
for n in self.subnodes:
print(n)
count+=len(n.subnodes)
return count
def __contains__(self, o):
# check if in subnodes of self
if o in self.subnodes:
return True
# check if in subnodes (recursive)
for n in self.subnodes:
if o in n:
return True
return False
def __getitem__(self, key):
return self.metadata[key]
def __setitem__(self, key, value):
self.metadata[key] = value
def __delitem__(self, key):
del self.metadata[key]
def __lt__(self, o):
return self in o
def __gt__(self, o):
return o in self
def append(self, o:"Node"):
"""
Appends an object as children.
# Arguments #
o:Node | Node object.
"""
self.subnodes.append(o)
def insert(self, i:int, o:"Node"):
"""
Inserts an object to given index.
# Arguments #
i:int | Index
o:Node | Node object
"""
self.subnodes.insert(i, o)
def remove(self, o:"Node"):
"""
Removes an object from subnodes.
# Arguments #
o:Node | Node object
"""
self.subnodes.remove(o)
def is_leafnode(self):
"""
Is this node a leaf node?
"""
return len(self) == 0
def search(self, **query):
"""
Searches tree with metadata.
**query:dict | Searching query.
"""
return [d for d in self.metadata if all(d.get(k, object()) == v for k, v in query.items())]
我通过append
对象的Node
函数添加子节点。但是,subnodes
属性就好像它是静态属性一样。
我的期望是:
但是,所有对象的subnodes
属性都会返回:
我手动测试了它。我有6个Node
个对象,如下所示:
我想实现上面演示的结构。所以我做了:
a.append(b) # a => b
a.append(c) # a => c
b.append(d) # b => d
b.append(e) # b => e
c.append(f) # c => f
但是,当我调用任何subnodes
对象的Node
属性时:
a.subnodes # [<[b] None>, <[c] None>, <[d] None>, <[e] None>, <[f] None>]
b.subnodes # [<[b] None>, <[c] None>, <[d] None>, <[e] None>, <[f] None>]
# ...
# rest is the same
答案 0 :(得分:1)
您的问题似乎是由Default Parameter Value问题造成的。
这意味着在创建类subnodes=list()
期间,定义__init__
中的默认参数Node
只进行了一次评估。从这一点开始,每当您实例化一个新对象时,相同的可变对象将被用作默认值。由于这是一个可变对象,无论何时向self.subnodes
追加内容,实际上都是在修改默认值。在this question中有一个非常详细的讨论。
基本上,Python中的规则是从不使用可变数据类型作为默认参数值。相反,请使用None
,并明确指定默认值,如下所示:
class Node:
def __init__(self, metadata={"label": None, "content": None, "description": None}, subnodes=None):
self.metadata = metadata
if subnodes is None:
self.subnodes = []
else:
self.subnodes = subnodes