Hac*_*ife 7 python tree parent-child
我有一个带有属性的简单类,该属性可以包含同一类的对象列表
class BoxItem:
def __init__(self, name, **kw):
self.name = name
self.boxItems = []
... #more attributes here
box1 = BoxItem('Normal Box')
box2 = BoxItem('Friendly Box')
box3 = BoxItem('Cool Box')
box4 = BoxItem('Big Box', [box1, box2]) #contains some children
example = BoxItem('Example Box', [box4,box3]) #contains another level of children
Run Code Online (Sandbox Code Playgroud)
使用我们的'示例'框对象,我想操纵它可能具有的所有可能的盒子的深度,并打印出如下格式的对象:
1 Example Box
1.1 Big Box
1.1.1 Normal Box
1.1.2 Friendly Box
1.2 Cool Box
Run Code Online (Sandbox Code Playgroud)
不需要Tabbing,只是想清楚地显示树格式.我能够自己走下来并打印出他们的标题,但是我无法打印显示父/子关系的前面数字.(1,1.1,1.2 ...)
在此先感谢您的帮助 :)
编辑 这是我到目前为止一直在使用的内容
def print_boxes(box_list):
node_count = 0
for box in box_list:
node_count += 1
print str(node_count)+' '+box.name #prints out the root box
recursive_search(box,node_count)
def recursive_search(box,node_count): #recursive automatically
level = 0
for child in box.boxItems:
level += 1
for x in range(len(child.boxItems)):
print x+1 #this prints out some proper numbers
print "level: "+str(level) #experiment with level
print child.name #prints out child box name
recursive_search(child,node_count) #runs the function again inside the function
Run Code Online (Sandbox Code Playgroud)
我想如果我发布一个如何执行此操作的工作示例,而不是通过代码遇到问题的地方,那么对您来说可能会更有帮助.我们可能会以这种方式更快地达到理解的程度.您的代码有正确的想法,它需要跟踪深度.但它唯一缺少的是嵌套深度(树).它只知道前一个node_count,然后它当前的子计数.
我的示例使用闭包来启动深度跟踪对象,然后创建一个内部函数来执行递归部分.
def recurse(box):
boxes = not isinstance(box, (list, tuple)) and [box] or box
depth = [1]
def wrapped(box):
depthStr = '.'.join([str(i) for i in depth])
print "%s %s" % (depthStr, box.name)
depth.append(1)
for child in box.boxItems:
wrapped(child)
depth[-1] += 1
depth.pop()
for box in boxes:
wrapped(box)
depth[0] += 1
Run Code Online (Sandbox Code Playgroud)
示例的示例输出:
>>> recurse(example)
1 Example Box
1.1 Big Box
1.1.1 Normal Box
1.1.2 Friendly Box
1.2 Cool Box
>>> recurse([example, example])
1 Example Box
1.1 Big Box
1.1.1 Normal Box
1.1.2 Friendly Box
1.2 Cool Box
2 Example Box
2.1 Big Box
2.1.1 Normal Box
2.1.2 Friendly Box
2.2 Cool Box
Run Code Online (Sandbox Code Playgroud)
打破这个:
我们首先接受一个box参数,如果你只传入一个盒子项,它会自动将它本地转换为一个列表.这样你就可以传递一个盒子对象,或者它们的列表/元组.
depth是我们的深度跟踪器.它是一个我们将在递归发生时建立和缩小的整数列表.它从第一个项目/第一级别的1开始.随着时间的推移,它看起来像这样:[1,1,2,3,1]取决于它穿越的深度.这是我的代码和你的代码之间的主要区别.每次递归都可以访问此状态.
现在我们有了这个内在的wrapped功能.它将获取当前的盒子项并打印它,然后迭代它的子项.我们通过加入当前深度列表,然后是名称来获取我们的打印字符串.
每次我们下载到子列表中时,我们都会在我们的深度列表中添加一个起始级别1,当我们从该子循环中退出时,我们会再次将其弹出.对于该循环中的每个子项,我们将最后一项递增.
在那个wrapped内部函数之外,我们然后通过循环我们的初始框,调用wrapped然后递增我们的第一级来启动整个事情.
内部包装函数在闭包中使用深度列表.我愿意打赌其他人可以对此提供一些进一步的改进,但这是我想出的一个例子.
注意函数的args
我们也可以设计recurse为采用可变长度参数列表,而不是检查列表.它看起来像这样(并将摆脱第一次boxes =检查):
def recurse(*boxes):
#boxes will always come in as a tuple no matter what
>>> recurse(example)
>>> recurse(example, example, example)
Run Code Online (Sandbox Code Playgroud)
如果您最初从一个盒子项目列表开始,您可以通过执行以下操作来传递它:
>>> boxes = [example, example, example]
>>> recurse(*example) # this will unpack your list into args
Run Code Online (Sandbox Code Playgroud)