我是一个编程新手,并且在理解我的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)
也许你的困惑的一部分是你正在考虑最终的yield
陈述,好像它是一个return
陈述.实际上,有几个人建议当a TypeError
抛出此代码时,传递的项目将"返回".事实并非如此!
请记住,任何时间yield
出现在函数中,结果不是单个项目,而是可迭代 - 即使序列中只出现一个项目.因此,当您1
转到时flatten
,结果是一个项目生成器.要从中获取项目,您仍需要迭代它.
由于这个单项生成器是可迭代的,所以TypeError
当内for
循环试图迭代它时它不会抛出; 但内for
循环只执行一次.然后外部for
循环移动到嵌套列表中的下一个iterable.
思考这个另一种方式是说,你每次通过一个非可迭代的价值flatten
,它在一个项目迭代和"收益",它包装的价值.