魔法压扁法是如何工作的?

2024-03-29 11:06:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我在读《从新手到专业的python入门》,里面有一个神奇的flatten函数让我很困惑。你知道吗

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

我知道yield返回一个元素。假设我有一个列表L = [ 1, [[2]] ]。 我用这个flatte()来称呼它,比如:

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

1
2

我真的很困惑,当我们调用for循环时,会不会触发flatten(),我们看到第一个元素1,它无疑会导致try块中的TypeError,except块中返回的nested变量不应该是整个列表[1, [[2]] ]?为什么它会返回1?你知道吗


Tags: 函数in元素列表for专业elementnested
3条回答

输入一个打印语句来查看发生了什么是很有帮助的。例如

#! /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

也许不使用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?的答案。你知道吗

我想我明白这里发生了什么。你知道吗

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。你知道吗

事情解释清楚了!你知道吗

相关问题 更多 >