<p>我认为,如果我发布一个关于如何做到这一点的工作示例,而不是查看您的代码遇到问题的地方,可能会对您更有帮助。这样我们可能会更快地理解。你的代码有一个正确的想法,那就是它需要在运行时跟踪深度。但它唯一缺少的是嵌套深度(树)的感觉。它只知道前一个<code>node_count</code>,然后知道当前的子计数。</p>
<p>我的示例使用闭包启动深度跟踪对象,然后创建一个内部函数来执行递归部分。</p>
<pre><code>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
</code></pre>
<p>示例输出示例:</p>
<pre><code>>>> 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
</code></pre>
<p><strong>分解:</strong></p>
<p>我们首先接受一个box参数,如果只传入了一个box项,则会自动将其本地转换为列表。这样就可以传递一个box对象,或者传递一个列表/元组。</p>
<p><code>depth</code>是我们的深度跟踪器。它是一个int列表,当递归发生时,我们将建立并缩小它。第一项/第一级从1开始。随着时间的推移,它可能看起来像这样:<code>[1,1,2,3,1]</code>这取决于它穿越的深度。<strong>这是我的代码与您的代码之间的主要区别。每个递归都可以访问此状态。</p>
<p>现在我们有了这个内在的<code>wrapped</code>功能。它将获取一个当前的box项并打印它,然后遍历它的子项。我们通过加入当前深度列表和名称来获取打印字符串。</p>
<p>每次我们进入子列表时,我们都会在深度列表中添加一个起始级别1,当我们从子循环中出来时,我们会再次弹出它。对于该循环中的每个子项,我们将最后一项递增。</p>
<p>在这个<code>wrapped</code>内部函数之外,我们通过循环初始框开始整个过程,调用<code>wrapped</code>,然后递增第一个级别。</p>
<p>内部包装函数在闭包中使用深度列表。我敢打赌,其他人可以在这方面提供一些进一步的改进,但这是我想出的一个例子。</p>
<p><strong>注意函数的参数</strong></p>
<p>我们还可以设计<code>recurse</code>来代替使用可变长度的参数列表,而不是检查列表。它看起来是这样的(并且会去掉第一个<code>boxes =</code>检查):</p>
<pre><code>def recurse(*boxes):
#boxes will always come in as a tuple no matter what
>>> recurse(example)
>>> recurse(example, example, example)
</code></pre>
<p>如果最初是以框项目列表开始,则可以通过执行以下操作传递:</p>
<pre><code>>>> boxes = [example, example, example]
>>> recurse(*example) # this will unpack your list into args
</code></pre>