通过对象和子对象进行Python递归,打印子深度编号
问题内容:
我有一个简单的类,其属性可以包含相同类的对象列表
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
使用“示例”框对象,我想对它可能具有的所有可能的框子项进行深入的操作,并打印出格式如下的对象:
1 Example Box
1.1 Big Box
1.1.1 Normal Box
1.1.2 Friendly Box
1.2 Cool Box
不需要Tab键,只是想清楚地显示树格式。我能够走动对象本身并打印出其标题,但无法打印出显示父子关系的前数字。(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
问题答案:
我认为,如果我发布一个如何执行此操作的示例,而不是遍历代码存在问题的地方,可能会对您有所帮助。这样,我们可能会更快地了解。您的代码具有正确的想法,即它需要跟踪深度。但是唯一缺少的是嵌套深度(树)的感觉。它只知道前一个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
您的示例的输出示例:
>>> 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
分解如下:
我们首先接受一个框参数,如果您只传递了一个框项目,则将其自动在本地转换为列表。这样,您既可以传递一个框对象,也可以传递它们的列表/元组。
depth
是我们的深度跟踪器。它是一个整数列表,随着递归发生,我们将逐步建立和缩小这些整数。对于第一项/第一级,它从1开始。随着时间的流逝,它看起来可能像这样:[1,1,2,3,1]
取决于遍历的深度。
这是我的代码与您的代码之间的主要区别 。每次递归都可以访问此状态。
现在我们有了这个内部wrapped
功能。它将采用当前的盒子项目并打印它,然后遍历其子项目。我们先加入当前深度列表,然后再加入名称,从而获得打印字符串。
每次我们下拉到一个子列表时,都会在深度列表中添加一个起始级别1,当我们退出该子循环时,会再次将其弹出。对于该循环中的每个孩子,我们将最后一项递增。
在该wrapped
内部函数之外,我们然后通过遍历初始框,调用wrapped
然后递增第一级来开始整个操作。
内部包装函数在闭包中使用深度列表。我愿意打赌,其他人可以对此做一些进一步的改进,但是我想出了一个例子。
关于函数的参数的注意事项
我们还可以设计recurse
成采用可变长度的参数列表,而不是检查列表。看起来像这样(并摆脱了第一个boxes =
检查):
def recurse(*boxes):
#boxes will always come in as a tuple no matter what
>>> recurse(example)
>>> recurse(example, example, example)
并且如果您最初是从一列盒子开始的,则可以通过执行以下操作来传递它:
>>> boxes = [example, example, example]
>>> recurse(*example) # this will unpack your list into args