为了账号安全,请及时绑定邮箱和手机立即绑定

《Python基础教程》里P121有关生成器处理多层嵌套列表的问题

《Python基础教程》里P121有关生成器处理多层嵌套列表的问题

拉风的咖菲猫 2019-02-26 02:29:36
以下是书中一道例程: def flatten(nested): try: # 不迭代类似于字符串的对象 try: nested + '' except TypeError: pass else: raise TypeError for sublist in nested: for element in flatten(sublist): yield element except TypeError: yield nested a = list(flatten([[[1], 'abc'], 3, 4, [5, [6, 7]], [[[8, 9, 10], 11], 12], 13, 14])) print(a) 按照如书上所说,上面的程序应当报错,可是实际我在pycharm中运行却是成功的,方法定义部分和书中一样,我只是在后面添加了输出语句。实在不明白其中的原理,尤其是raise TypeError,讲其换作raise SyntaxError后,程序就能报错了,我在想是不是两个TypeError会有什么相互作用吗?求解...
查看完整描述

1 回答

?
慕斯王

TA贡献1864条经验 获得超2个赞

程序是对的, 给的例子也是对的, 我认为上面的程序不应当报错.
这段程序设计flatten函数的意义是将树形结构按照深度优先顺序进行迭代. 可以实现将一个树形结构"压扁"成列表结构.
比如:

tree = [
    ['1', 2, [3]],
    ['4', 5]
]
list(flatten(tree))    # 得到 ['1', 2, 3, '4', 5]

而对于这段代码

        # 不迭代类似于字符串的对象
        try:
            nested + ''
        except TypeError:
            pass
        else:
            raise TypeError

注释标明了是为了不迭代字符串对象. 如果缺少了这一段, 那么程序就会在遇到迭代对象中包含字符串的时候陷入一直迭代的无限循环. 这是因为字符串也是可迭代对象.

比如输入'abc', 那么原函数里层try语句就会raise TypeError, 这个TypeError被外层try语句except TypeError捕捉到, 就直接将'abc'作为迭代结果输出去了.
如果输入不可迭代对象, 比如123, 那么在执行nested + ''的时候就会因为except TypeErrorpass, 继续执行for sublist in nested, 但是123是int类型, 不是可迭代对象, 所以会抛出TypeError: 'int' object is not iterable, 这个错误同样被外层的try语句捕捉到, 123就作为迭代结果输出.
只有非字符串的可迭代对象才会进入for sublist in nested中.

如果缺少了里面那个try语句, 那么就会执行for sublist in nested:, 这里的nested就是'abc', 那么就会迭代'a', 'b', 'c', 迭代到'a'的时候返回'a', 由于'a'又是可迭代的, 于是又迭代返回'a', 这样程序就会陷入一直迭代'a'的无限循环过程, 最后会抛出RecursionError.

所以flatten这个函数的设计是没问题的, 它完成了设计者期待它需要实现的功能.

查看完整回答
反对 回复 2019-03-01
  • 1 回答
  • 0 关注
  • 504 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信