关于python:如何解压深嵌套的可迭代结构

How to unpack deep nested iterable structure

例如,我有一个包含许多子元素的结构,其中一些是结构:

1
v = [1, 2, 3, [4, (5, 6)]]

如何将这些解包成一系列仅包含结构内容而不包含结构内容的名称?

尝试a, b, c, d, e, f = v会在使用星型表达式时引发ValueError,这将为名称指定一个结构。我如何打开它们以获得:

1
print(a, b, c, d, e, f)

要打印:

1
1 2 3 4 5 6


赋值是递归定义的,您需要使用括号()和/或方括号[]来括住目标名称并匹配iterable的嵌套结构。在您的情况下:

1
2
3
a, b, c, (d, (e, f)) = v
print(a, b, c, d, e, f)
1 2 3 4 5 6

同样,在语义不变的情况下,可以使用[]表示结构:

1
2
3
a, b, c, [d, [e, f]] = v
print(a, b, c, d, e, f)
1 2 3 4 5 6

或者,当然,把它们混在一起。

然后,python将解包v并正常分配前3个值,然后解包(d, (e, f))的内容并分配d,然后再次解包(e, f)并执行相同的操作。

如果导入dis模块并使用dis.dis分解语句,则可以看到这种情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
dis.dis('a, b, c, (d, (e, f)) = v')
  1           0 LOAD_NAME                0 (v)
              3 UNPACK_SEQUENCE          4      # <- first unpack
              6 STORE_NAME               1 (a)
              9 STORE_NAME               2 (b)
             12 STORE_NAME               3 (c)
             15 UNPACK_SEQUENCE          2      # <- second unpack
             18 STORE_NAME               4 (d)
             21 UNPACK_SEQUENCE          2      # <- third unpack
             24 STORE_NAME               5 (e)
             27 STORE_NAME               6 (f)
             30 LOAD_CONST               0 (None)
             33 RETURN_VALUE

通常,要解包任意嵌套的结构,请匹配分配左侧的结构(目标列表):

1
2
3
4
v = [1, [2, [3, [4, 5]]]]    
[a, [b, [c, [d, e]]]] = v    
print(a, b, c, d, e)
1 2 3 4 5

当然,外部[]是不必要的,只需添加它们就可以证明简单地匹配结构就足够了。


您可能会考虑的另一个选项是展平结构,然后分配它。

1
2
3
4
5
6
7
def flatten(container):
    for i in container:
        if isinstance(i, (list,tuple)):
            for j in flatten(i):
                yield j
        else:
            yield i

然后

1
a, b, c, d, e, f = flatten(v)