Chu*_*ner 3 python recursion list generator python-3.x
我正在使用Python中的生成器,我正在尝试使用简单的递归方案来实现flatten-function.也就是说,一个函数将一个列表作为输入,该列表可能包含子列表,并输出一个只能在输入的原子元素上迭代的可迭代对象.
所以,print(list(flatten([1,2,3,[4,5,6]])))
应该返回包含的内容[1,2,3,4,5,6]
.
我的尝试如下:
def flatten(toflatten):
try:
for element in toflatten:
flatten(element)
except TypeError:
yield toflatten
Run Code Online (Sandbox Code Playgroud)
因此,它应检查其参数是否是可迭代对象.如果是这种情况,也可以对此对象进行递归.否则,将其作为原子元素.
这不起作用,flatten([1,2,3,[4,5,6]])
只返回一个空列表.
为什么会这样?特别是; 为什么它甚至没有对此输入执行递归函数调用?(我使用的是Python 3.5)
所以,你试图压扁一个列表.你走在正确的轨道上,但你犯了几个错误.他们来了.
移动你的try-except
内循环.使用您的代码,如果TypeError
为一个元素引发a ,则循环停止运行.你不希望发生这种情况.
在尝试中,你什么都不产生.只进行函数调用.你也应该从那里归还一些东西.yield from
如果你有python3.3 +,我建议你.
最后,在except
,你需要yield element
,而不是toflatten
.不要产生整个列表.
def flatten(toflatten):
for element in toflatten:
try:
yield from flatten(element)
except TypeError:
yield element
Run Code Online (Sandbox Code Playgroud)
这给了,
>>> list(flatten([1,2,3,[4,5,6]]))
[1, 2, 3, 4, 5, 6]
Run Code Online (Sandbox Code Playgroud)
您已经使用了EAFP(比请求更容易请求宽恕),这很好.这是一种方法(实际上我最喜欢的),但有一个缺点:这会在字符串上崩溃.
还有另一种方法:LYBL(在你跳跃之前看).它包括更谨慎,使用if
语句,因此不会引发错误.
def flatten(toflatten):
for element in toflatten:
if isinstance(element, list):
yield from flatten(element)
else:
yield element
Run Code Online (Sandbox Code Playgroud)
哪个和以前一样,并给出,
>>> list(flatten([1,2,3,[4,5,6]]))
[1, 2, 3, 4, 5, 6]
Run Code Online (Sandbox Code Playgroud)
然而,这是有利的,因为yield from
仅在子列表上调用生成器委托.我提到它也适用于字符串元素吗?
>>> list(flatten([1,2,3,[4,5,'abc']]))
[1, 2, 3, 4, 5, 'abc']
Run Code Online (Sandbox Code Playgroud)
请注意,在任何一种情况下,如果您有递归定义的列表,则无限递归的警告.例如,flatten
这种输入会崩溃.
x = [1, 2, 3]
x.append(x)
flatten(x)
Run Code Online (Sandbox Code Playgroud)
您最终会收到运行时错误:
RuntimeError: maximum recursion depth exceeded
Run Code Online (Sandbox Code Playgroud)