<p>函数<code>f</code>返回深度优先搜索遇到的第一个平面列表的(浅)<strong>副本。你知道吗</p>
<p>为什么?首先让我们看看<em>基本情况</em>:一个包含<strong>no</strong>列表的列表。就像<code>[1,'a',2,5]</code>。在这种情况下,<code>if</code>语句将<strong>始终</strong>成功,因此<code>e</code>的所有元素都将添加到<code>result</code>并返回<code>result</code>。你知道吗</p>
<p>那么递归的情况呢。这意味着有一个列表元素。比如<code>[1,['a',2],5]</code>。现在对于第一个元素,<code>if</code>成功,因此<code>1</code>被添加到<code>result</code>列表中。但是对于第二个元素<code>['a',2]</code>,<code>if</code><strong>失败了。这意味着我们使用<code>['a',2]</code>对<code>f</code>执行递归调用。现在由于该列表不包含任何子列表,我们知道它将返回该列表的副本。你知道吗</p>
<p>但是请注意,我们立即<code>return</code></strong>返回递归调用的结果。所以从我们使用<code>else</code>分支的那一刻起,<code>result</code>就不再重要了:我们将返回<code>f(e)</code>返回的内容。你知道吗</p>
<p>如果我们假设我们不能构造一个无限深的子列表循环(实际上我们可以,但在这种情况下,我们将得到一个堆栈溢出异常),我们最终将获得一个平面列表并获得该副本。你知道吗</p>
<p><strong>示例</strong>:如果我们采用您的示例输入<code>[1, [[2, 'a'], ['a','b']], (3, 4)]</code>。我们可以追踪通话。因此,我们首先对该列表调用<code>f</code>,它将生成以下“trace”:</p>
<pre><code># **trace** of an example function call
f([1, [[2, 'a'], ['a','b']], (3, 4)]):
result = []
# for 1 in L:
# if type(1) == list: # fails
# else
result.append(1) # result is now [1]
# for [[2,'a'],['a','b']] in L:
# if type([[2,'a'],['a','b']]) == list: succeeds
<b>return</b> f([[2,'a'],['a','b']])
result = []
# for [2,'a'] in L:
# if type([2,'a']) == list: succeeds
<b>return</b> f([2,'a'])
result = []
# for 2 in L:
# if type(2) == list: fails
# else:
result.append(2) # result is now [2]
# for 'a' in [2,'a']:
# if type('a') == list: fails
# else:
result.append('a') # result is now [2,'a']
<b>return</b> [2,'a']
<b>return</b> [2,'a']
<b>return</b> [2,'a']</code></pre>
<p><strong>扁平化</strong>:</p>
<p>如果希望将列表展平,而不是返回第一个平面列表,可以将代码重写为:</p>
<pre><code>def f(L):
result = []
for e in L:
if type(e) != list:
result.append(e)
else:
<b>result +=</b> f(e)
return result</code></pre>
<p>请注意,这将仅展平<code>list</code>s</strong>(甚至不展平<code>list</code>s的子类)。你知道吗</p>