Python递归通过对象和子对象,打印子深度数 [英] Python Recursion through objects and child objects, Print child depth numbers

查看:57
本文介绍了Python递归通过对象和子对象,打印子深度数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的类,其属性可以包含同一类的对象列表

 类 BoxItem:def __init__(self, name, **kw):self.name = 姓名self.boxItems = []... #more 属性在这里box1 = BoxItem('普通框')box2 = BoxItem('友好盒子')box3 = BoxItem('Cool Box')box4 = BoxItem('Big Box', [box1, box2]) #包含一些孩子example = BoxItem('Example Box', [box4,box3]) #包含另一个级别的孩子

使用我们的示例"框对象,我想通过它可能拥有的所有可能的框子对象的深度进行操作,并打印出如下格式的对象:

1 示例框1.1 大盒子1.1.1 普通框1.1.2 友好盒子1.2 冷藏箱

不需要Tabbing between,只是想清楚地显示树格式.我能够自己走下对象并打印出它们的标题,但我无法打印出显示父/子关系的前面的数字.(1, 1.1, 1.2...)

预先感谢您的帮助:)

编辑这是我迄今为止一直在使用的内容

def print_boxes(box_list):节点计数 = 0对于 box_list 中的框:节点数 += 1print str(node_count)+' '+box.name #打印出根框recursive_search(box,node_count)def recursive_search(box,node_count): #recursive自动等级 = 0对于 box.boxItems 中的孩子:等级 += 1对于范围内的 x(len(child.boxItems)):print x+1 #this 打印出一些正确的数字print "level: "+str(level) #用级别进行实验print child.name #打印出子框名称recursive_search(child,node_count) #在函数内部再次运行该函数

解决方案

我认为如果我发布一个如何执行此操作的工作示例,而不是查看您的代码有问题的地方,这可能对您更有帮助.这样我们可能会更快地理解这一点.你的代码有正确的想法,它需要跟踪深度.但它唯一缺少的是嵌套深度(树)的感觉.它只知道之前的 node_count,然后是它当前的子节点计数.

我的示例使用闭包来启动深度跟踪对象,然后创建一个内部函数来完成递归部分.

def recurse(box):box = not isinstance(box, (list, tuple)) 和 [box] 或 box深度 = [1]定义包装(盒):depthStr = '.'.join([str(i) for i in depth])打印 "%s %s" % (depthStr, box.name)深度.附加(1)对于 box.boxItems 中的孩子:包裹(孩子)深度[-1] += 1深度.pop()对于盒中盒:包裹(盒)深度[0] += 1

示例的输出示例:

<预><代码>>>>递归(示例)1 示例框1.1 大盒子1.1.1 普通框1.1.2 友好盒子1.2 冷藏箱>>>递归([示例,示例])1 示例框1.1 大盒子1.1.1 普通框1.1.2 友好盒子1.2 冷藏箱2 示例框2.1 大盒子2.1.1 普通框2.1.2 友好盒子2.2 冷藏箱

分解:

我们首先接受一个 box 参数,并在本地自动将其转换为列表,如果您只传入一个 box 项目.这样你就可以传递一个盒子对象,或者它们的列表/元组.

depth 是我们的深度跟踪器.它是一个整数列表,我们将在递归发生时建立和缩小这些整数.第一个项目/第一级从 1 开始.随着时间的推移,它可能看起来像这样:[1,1,2,3,1] 取决于它遍历的深度.这是我的代码和你的代码之间的主要区别.每个递归都可以访问此状态.

现在我们有了这个内部 wrapped 函数.它将获取当前的框项并打印它,然后迭代它的子项.我们通过加入当前深度列表和名称来获得我们的打印字符串.

每次我们下拉到子列表时,我们都会在深度列表中添加一个起始级别 1,当我们退出该子循环时,我们再次将其弹出.对于该循环中的每个子项,我们将最后一项递增.

在那个 wrapped 内部函数之外,我们然后通过循环我们的初始框开始整个事情,调用 wrapped 然后增加我们的第一级.

内部包装函数在闭包中使用深度列表.我敢打赌其他人可以对此提供一些进一步的改进,但这是我想出的例子.

注意函数的参数

我们也可以设计 recurse 来代替使用可变长度的参数列表,而不是检查列表.它看起来像这样(并且会去掉第一个 boxes = 检查):

def recurse(*boxes):#boxes 无论如何都会作为元组出现>>>递归(示例)>>>递归(示例,示例,示例)

如果您最初从一个盒子项目列表开始,您可以通过以下方式传递它:

<预><代码>>>>盒子 = [示例,示例,示例]>>>recurse(*example) # 这会将你的列表解压到 args

I have a simple class with an attribute that can contain a list of objects of the same class

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

Working with our 'example' box object, I would like to maneuver through the depths of all possible box children it may have, and print out the objects formatted like so:

1 Example Box
 1.1 Big Box
  1.1.1 Normal Box
  1.1.2 Friendly Box
 1.2 Cool Box

The Tabbing between isn't needed, just wanting to show the tree format clearly. I am able to walk down the objects themselves and print out their titles, but I am not able to print out the front numbers that show the parent/child relationship. (1, 1.1, 1.2...)

Thanks in advance for your help :)

Edit Here is what I have been working with so far

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

解决方案

I think it might be more helpful to you if I post a working example of how to do this, as opposed to going through where you code is having problems. We might get to the point of understanding a lot faster that way. Your code has the correct idea that it needs to track the depth as it goes. But the only thing it is missing is a sense of nested depth (tree). It only knows the previous node_count, and then its current child count.

My example uses a closure to start the depth tracking object, and then creates an inner function to do the recursive part.

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

Sample output from your examples:

>>> 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

Breaking this down:

We first accept a box argument, and automatically convert it locally to a list, if you had only passed in a single box item. That way you can pass either one box objects, or a list/tuple of them.

depth is our depth tracker. Its a list of ints that we will build up and shrink down as the recursion happens. It starts at 1 for the first item / first level. Over time it can look like this: [1,1,2,3,1] depending on how deep it traverses. This is the major difference between my code and yours. Each recursion has access to this state.

Now we have this inner wrapped function. Its going to take a current box item and print it, and then iterate over its children. We get our print string by joining the current depth list, and then the name.

Every time we drop down into a child list, we add a starting level 1 to our depth list, and when we come out of that child loop, we pop it back off again. For every child in that loop, we increment that last item up.

Outside of that wrapped inner function, we then start the whole thing by looping over our initial boxes, calling wrapped and then incrementing our first level.

The inner wrapped function uses the depth list in a closure. I am willing to bet that others can offer some further improvements on this, but its what I came up with for an example.

Note about the args for the function

We could have also designed recurse to instead take a variable length argument list, instead of checking for a list. It would look like this (and would get rid of that first boxes = check):

def recurse(*boxes):
    #boxes will always come in as a tuple no matter what

>>> recurse(example)
>>> recurse(example, example, example)

And if you originally start with a list of box items, you can pass it by doing:

>>> boxes = [example, example, example]
>>> recurse(*example)    # this will unpack your list into args

这篇关于Python递归通过对象和子对象,打印子深度数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆