神奇的扁平方法如何工作?

时间:2014-10-21 13:18:46

标签: python

我正在阅读“从初学者到专业人士的初学蟒蛇”,其中有一个让我感到困惑的神奇扁平化功能。

def flatten(nested):
    try:
        for sublist in nested:
            for element in flatten(sublist):
                yield element
    except TypeError:
        yield nested

我知道yield会返回一个元素。假设我有一个列表L = [ 1, [[2]] ]。 我称之为flatten(),如:

L = [ 1, [[2]] ]
for i in flatten(L):
    print i

1
2

我真的很困惑,当我们调用for循环时,我们不会对flatten()进行分析,并且我们看到了第一个元素1,这无疑会导致TypeError尝试阻止,在except块中返回的nested变量不应该是整个列表[1, [[2]] ]吗?为什么会返回1

3 个答案:

答案 0 :(得分:1)

也许在不使用yield的情况下重写函数可以让你更容易理解:

def flatten(nested):
    res = []
    try:
        for sublist in nested:
            for element in flatten(sublist):
                res.append(element)
    except TypeError:
        res.append(nested)
    return res

在最基本的术语中,这就是yield的作用。它发出了'函数中一次一个值。有关更完整的说明,请参阅What does the yield keyword do in Python?的答案。

答案 1 :(得分:1)

投入一份打印声明以查看正在进行的操作会很有帮助。例如,

#! /usr/bin/env python

def flatten(nested, depth=0):
    print "%d: %r" % (depth, nested)
    try:
        for sublist in nested:
            for element in flatten(sublist, depth+1):
                yield element
    except TypeError:
        yield nested


def main():
    L = [ 1, [[2]] ]
    for i in flatten(L):
        print "output %s\n" % i


if __name__ == '__main__':
    main()

<强>输出

0: [1, [[2]]]
1: 1
output 1

1: [[2]]
2: [2]
3: 2
output 2

答案 2 :(得分:0)

我想我明白现在发生了什么。

def flatten(nested):
    try:
        for sublist in nested:
            for element in flatten(sublist):
                yield element
    except TypeError:
        yield nested

我们仍然有L = [1, [[2]]],我们致电flatten(L)

现在第一个元素是1,现在我们已经转移到for element in flatten(1)

当我们调用flatten()并遇到TypeError时,我们将获得nested变量,此处为1。

所以我们得到1

原来的L现在只留下[[2]]

当我们调用for循环:for i in flatten(L)时,事情就会继续。

我们现在转到for element in flatten([[2]]),是的,我们下方有yield element,但我们必须先执行for element in flatten([[2]]),然后看看发生了什么。

现在我们将转移到for element in flatten([2]),这是一种直接进入yield element以下的诱惑。但是等一下,让我们进一步压扁。

现在我们已经转移到flatten(2),它会像flatten(1)那样引发TypeError。

这次我们得到2

事情解释了!

相关问题