且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在Python中递归展平嵌套列表

更新时间:2022-06-09 07:07:19

因此,您正在尝试拼合列表.您走在正确的道路上,但是您犯了一些错误.他们在这里.

So, you're trying to flatten a list. You're on the right track but you've made a couple of mistakes. Here they are.

  1. 在循环中移动try-except .对于您的代码,如果为一个元素引发TypeError,则循环停止运行.您不希望发生这种情况.

  1. Move your try-except inside the loop. With your code, if a TypeError is raised for one element, then the loop stops running. You don't want that happening.

在尝试中,您什么也不会产生.仅进行函数调用.您也应该从那里返回一些东西.如果您有python3.3 +,我建议yield from.

In the try, you yield nothing. Only making a function call. You should be returning something from there as well. I'd recommend yield from if you have python3.3+.

最后,在except中,您需要yield element,而不是toflatten.不要产生整个列表.

Finally, in the except, you need to yield element, not toflatten. Don't yield the entire list.

def flatten(toflatten):    
   for element in toflatten:
       try:
           yield from flatten(element)
       except TypeError:
           yield element

这给出了

>>> list(flatten([1,2,3,[4,5,6]]))
[1, 2, 3, 4, 5, 6]

您已经使用了EAFP(比许可更容易寻求宽恕).这是执行此操作的一种方法(实际上是我的最爱),但是有一个缺点:这会在字符串上崩溃.

You've used the EAFP (Easier to Ask Forgiveness, than Permission), which is nice. That's one way to do it (my favourite, actually), but there's a drawback: This crashes on strings.

还有另一种方法:LYBL(跳跃前先看).它包括更加谨慎,使用if语句,因此不会引发错误.

There's another approach: LYBL (Look Before You Leap). It consists of being more cautious, using if statements so errors are not raised.

def flatten(toflatten):    
   for element in toflatten:
       if isinstance(element, list):
           yield from flatten(element)
       else:
           yield element

工作原理与以前相同,并且给出了

Which works the same as before, and gives,

>>> list(flatten([1,2,3,[4,5,6]]))
[1, 2, 3, 4, 5, 6]

但是,这是有利的,因为yield from生成器委派仅在子列表上被调用.我是否提到过它也适用于字符串元素?

However, this is advantageous, in the fact that the yield from generator delegation is only invoked upon sub-lists. Did I mention it also works with string elements?

>>> list(flatten([1,2,3,[4,5,'abc']]))
[1, 2, 3, 4, 5, 'abc']


请注意,无论哪种情况,如果您具有递归定义的列表,都需要注意无限递归.例如,flatten会因此类输入而崩溃.


Note that in either case, the caveat of infinite recursion, if you have recursively defined lists. For example, flatten will crash with this sort of input.

x = [1, 2, 3]
x.append(x)

flatten(x)

您最终会遇到运行时错误:

You'll end up getting a runtime error:

RuntimeError: maximum recursion depth exceeded