用于展平嵌套列表的递归生成器

Wit*_*wel 9 python recursion

我是一个编程新手,并且在理解我的python教科书(Magnus Lie Hetland的"Beginning Python")中的一个例子时遇到了一些麻烦.该示例用于递归生成器,旨在展平嵌套列表的元素(具有任意深度):

def flatten(nested):
    try:
        for sublist in nested:
            for element in flatten(sublist):
                yield element
    except TypeError:
        yield nested
Run Code Online (Sandbox Code Playgroud)

然后,您将按如下方式提供嵌套列表:

>>> list(flatten([[[1],2],3,4,[5,[6,7]],8]))
[1,2,3,4,5,6,7,8]
Run Code Online (Sandbox Code Playgroud)

我理解flatten()中的递归如何帮助减少到这个列表的最内层元素'1',但是我不明白当'1'实际上作为'嵌套传递回flatten()时会发生什么".我认为这会导致TypeError(不能迭代一个数字),并且异常处理实际上是用于生成输出的繁重工作......但是使用flatten()的修改版本进行测试已经说服了我事实并非如此.相反,似乎'yield element'行是负责任的.

那就是说,我的问题是......如何"屈服元素"实际上被执行?似乎'嵌套'将是一个列表 - 在这种情况下添加另一层递归 - 或者它是一个数字,你得到一个TypeError.

任何对此的帮助都将非常感激...特别是,我喜欢在事件链中走动,因为flatten()处理一个简单的例子:

list(flatten([[1,2],3]))
Run Code Online (Sandbox Code Playgroud)

Hug*_*ell 13

我在函数中添加了一些工具:

def flatten(nested, depth=0):
    try:
        print("{}Iterate on {}".format('  '*depth, nested))
        for sublist in nested:
            for element in flatten(sublist, depth+1):
                print("{}got back {}".format('  '*depth, element))
                yield element
    except TypeError:
        print('{}not iterable - return {}'.format('  '*depth, nested))
        yield nested
Run Code Online (Sandbox Code Playgroud)

现在打电话

list(flatten([[1,2],3]))
Run Code Online (Sandbox Code Playgroud)

显示器

Iterate on [[1, 2], 3]
  Iterate on [1, 2]
    Iterate on 1
    not iterable - return 1
  got back 1
got back 1
    Iterate on 2
    not iterable - return 2
  got back 2
got back 2
  Iterate on 3
  not iterable - return 3
got back 3
Run Code Online (Sandbox Code Playgroud)


sen*_*rle 6

也许你的困惑的一部分是你正在考虑最终的yield陈述,好像它是一个return陈述.实际上,有几个人建议当a TypeError抛出此代码时,传递的项目将"返回".事实并非如此!

请记住,任何时间yield出现在函数中,结果不是单个项目,而是可迭代 - 即使序列中只出现一个项目.因此,当您1转到时flatten,结果是一个项目生成器.要从中获取项目,您仍需要迭代它.

由于这个单项生成器是可迭代的,所以TypeError当内for循环试图迭代它时它不会抛出; 但内for循环只执行一次.然后外部for循环移动到嵌套列表中的下一个iterable.

思考这个另一种方式是说,你每次通过一个非可迭代的价值flatten,它在一个项目迭代和"收益",它包装的价值.