【问题标题】:How to unpack deep nested iterable structure如何解压深层嵌套的可迭代结构
【发布时间】:2016-12-07 20:04:50
【问题描述】:

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

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

我怎样才能将它们解压成一系列只包含结构内容而不包含结构的名称?

尝试a, b, c, d, e, f = v 会引发ValueError,而使用星号表达式会为名称分配结构。我怎样才能打开它们以获得:

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

打印:

1 2 3 4 5 6

【问题讨论】:

    标签: python python-3.x iterable iterable-unpacking


    【解决方案1】:

    分配是递归定义的,您需要 use parentheses () and/or square brackets [] to enclose target names 并匹配您的可迭代对象的嵌套结构。在你的情况下:

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

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

    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 反汇编语句,您会看到这种情况:

    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
    

    一般来说,要解包任意嵌套的结构,匹配左边的结构赋值(target-list):

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

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

    【讨论】:

      【解决方案2】:

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

      def flatten(container):
          for i in container:
              if isinstance(i, (list,tuple)):
                  for j in flatten(i):
                      yield j
              else:
                  yield i
      

      然后

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

      【讨论】:

      • 您可以使用isinstance(i, Container)collections.abc 中的Container 来捕获所有容器,而不仅仅是listtuple 类型。
      • @JimFasarakisHilliard:尽管您可能希望明确排除或特殊情况 str(可能还有 bytes 和相关类型),因为它们算作 Containers 但通常就像它们是标量一样使用。
      猜你喜欢
      • 2014-06-19
      • 2019-12-13
      • 1970-01-01
      • 2017-05-11
      • 1970-01-01
      • 2023-01-16
      • 2021-04-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多