打印分层树的编号轮廓

时间:2013-12-25 14:29:51

标签: python-3.x blender

我正在尝试编写一个打印对象层次树的函数(在Blender 3D中,但这是一般的Python问题),带有十进制大纲编号。

我要求:

  • 包含"+""--"或无缩进""等任何符号的可选缩进,
  • 可选地附加".0"到具有子节点的节点,以区分树枝和树叶。

例如,在Blender中,我创建了一个骨骼和层次结构的骨架,如下所示:

+ Life
++ Bacteria
++ Eukaryota
+++ plants
+++ animals
++++ Vertebrates
+++++ amphibians
+++++ reptiles
+++++ mammals

在de Text Editor中,我创建了这个基本脚本:

import bpy
D = bpy.data
root = D.armatures['Armature'].bones['Life']

def print_hierarchy(obj, indent = "+"):
    print(indent, obj.name)
    for child in obj.children:
        print_hierarchy(child, indent+"+")
print_hierarchy(root)

此脚本输出:

+ Life
++ Bacteria
++ Eukaryota
+++ plants
+++ animals
++++ Vertebrates
+++++ amphibians
+++++ reptiles
+++++ mammals

我希望它看起来像这样

1.0 Life
    1.1 Bacteria
    1.2.0 Eukaryota
        1.2.1 plants
        1.2.2.0 animals
            1.2.2.1.0 Vertebrates
                1.2.2.1.1 amphibians
                1.2.2.1.2 reptiles
                1.2.2.1.3 mammals

我已经使用(递归)函数print_hierarchy()进行了修改,但每当我尝试添加新内容时它就会中断。我无法将我的大脑包裹起来,所以我想请一些帮助。

对于这种事情,while循环是否比递归函数更好/更有效/更快?

2 个答案:

答案 0 :(得分:1)

这样做会更容易。

1 Life
    1.1 Bacteria
    1.2 Eukaryota
        1.2.1 plants
        1.2.2 animals
              1.2.2.1 Vertebrates
              1.2.2.1.1 amphibians
              1.2.2.1.2 reptiles
              1.2.2.1.3 mammals

那时你不必明确检查节点是否有子节点print。一些有用的代码:

for index, child in enumerate(obj.children, 1):

这将使用基于一个的索引对每个children进行编号。

''.join(('\t', indent, '.', str(index)))

将新标签添加到上一个indent的开头,将index添加到结尾。将它们放在一起:

def print_hierarchy(root, indent="1"):
    print('\t'.join([indent, root.name]))
    for index, child in enumerate(root.children, 1):
        print_hierarchy(child, ''.join(('\t', indent, '.', str(index))))

我明白了:

1   life
    1.1 bacteria
    1.2 eukaryota
        1.2.1   plants
        1.2.2   animals
            1.2.2.1 vertebrates
                1.2.2.1.1   amphibians
                1.2.2.1.2   reptiles
                1.2.2.1.3   mammals

为了获得更全面的功能,它变得更加复杂:

def print_hierarchy(root, indent=None, dec=None, zeroes=False):
    if indent is None:
        indent = []
    elif isinstance(indent, str):
        indent = [indent]
    if dec is None:
        dec = []
        zeroes = False
    elif isinstance(dec, int):
        dec = [str(dec)]
    elif isinstance(dec, str):
        dec = [dec]
    print(' '.join([''.join(indent), 
                    '.'.join(dec + ["0"] if root.children and zeroes else dec), 
                    root.name]))
    for index, child in enumerate(root.children, 1):
        print_hierarchy(child, 
                        indent + [indent[0]] if indent else indent, 
                        dec + [str(index)] if dec else dec,
                        zeroes)

print_hierarchy(root, "\t", 1, True)

答案 1 :(得分:0)

您可以像这样更改递归函数:

>>> def print_hierarchy(obj, prefix = ''):
        print('{}{} {}'.format(prefix, '.0' if obj.children else '', obj.name))
        for num, child in enumerate(obj.children, 1):
            print_hierarchy(child, '    {}.{}'.format(prefix, num))

>>> print_hierarchy(root, '1')
1.0 Life
    1.1 Bacteria
    1.2.0 Eukaryota
        1.2.1 plants
        1.2.2.0 animals
            1.2.2.1.0 Vertebratens
                1.2.2.1.1 amphibians
                1.2.2.1.2 reptiles
                1.2.2.1.3 mammals

但我同意jonrsharpe的说法,编号对于层次结构来说并不合理。它使LifeBacteria处于同一级别,但Eukaryota不是。