【问题标题】:Difference between zip(list) and zip(*list) [duplicate]zip(list) 和 zip(*list) 之间的区别 [重复]
【发布时间】:2015-05-22 06:11:33
【问题描述】:

我正在使用列表p = [[1,2,3],[4,5,6]]

如果我这样做:

>>>d=zip(p)
>>>list(d)
[([1, 2, 3],), ([4, 5, 6],)]

虽然,我真正想要的是使用这个获得的:

>>>d=zip(*p)
>>>list(d)
[(1, 4), (2, 5), (3, 6)]

我发现在列表名称前添加“*”可以提供所需的输出,但我无法区分它们的操作。你能解释一下区别吗?

【问题讨论】:

    标签: python python-3.x


    【解决方案1】:

    zip 想要将一堆参数压缩在一起,但你只有一个参数(一个列表,其元素也是列表)。函数调用中的*“解包”一个列表(或其他可迭代的),使其每个元素成为单独的参数。所以没有*,你正在做zip( [[1,2,3],[4,5,6]] )。使用*,您正在执行zip([1,2,3], [4,5,6])

    【讨论】:

    • 我读过的关于解包操作符 * 的最佳解释。谢谢。
    【解决方案2】:

    * 运算符解压缩函数调用语句中的参数。

    考虑一下

    def add(x, y):
       return x + y
    

    如果你有一个列表t = [1,2],你可以说add(t[0], t[1]),它是不必要的冗长,或者你可以使用*操作符将t“解包”成单独的参数,就像add(*t)一样。

    这就是您的示例中发生的情况。 zip(p) 就像运行 zip([[1,2,3],[4,5,6]])。 Zip 在这里只有一个参数,所以它只是简单地将它作为一个元组返回。

    zip(*p) 就像运行zip([1,2,3], [4,5,6])。这类似于运行zip(p[0], p[1]),您将获得预期的输出。

    【讨论】:

      【解决方案3】:

      * 字符被称为解包运算符。当它出现在可迭代对象的后面时,它所做的就是将可迭代对象中的项目一一传递给函数的调用者。在这种情况下,由于zip 函数接受可迭代列表以返回其对齐的列,zip(*p)p 中的所有项目作为参数传递给 zip 函数:

      因此,在这种情况下,zip(*p) 等于:

      zip([1,2,3],[4,5,6])
      

      另外,请注意,从 Python-3.5 开始,除了函数调用者之外,您还可以在其他一些情况下使用解包运算符。其中之一称为就地拆包,它允许您在另一个可迭代对象中使用拆包。

      In [4]: a = [1, 2, 3]
      
      In [5]: b = [8, 9, *a, 0, 0]
      
      In [6]: b
      Out[6]: [8, 9, 1, 2, 3, 0, 0]
      

      【讨论】:

        【解决方案4】:

        简而言之,使用x = [1,2,3],当调用f(x) 时,x 接收到1 个参数[1, 2, 3]。使用星号运算符f(*x)时,f接收三个参数,相当于调用f(1,2,3)

        这就是为什么在 Python 的文档中,你会经常看到some_function(*args, **kwargs)。此处双星运算符的作用相同,但对于字典:使用d={"some_arg":2, "some_other_arg":3},调用f(**d)f(some_arg=2, some_other_arg=3) 相同。

        现在,当您使用 zip 时,实际上您希望将 [1,2,3] 与 [4,5,6] 一起压缩,因此您希望将 2 个 args 传递给 zip,因此您需要一个星号运算符。没有它,你只会传递一个参数。

        【讨论】:

        • 具有*** 的函数定义 就像您提到的那样,是* 运算符的不同用法。在这种情况下,它用于创建variadic functions。它们与 OP 正在谈论的 * 相关,这更像是 apply 运算符的语法糖。混淆他们两个是个坏主意。
        • 我认为它们是同一概念的两个方面(尽管行为不同)。在一种情况下(函数定义),您指定该函数将接受分组在一个名称(args)下的多个参数,而在另一种情况下,您将一个名称分配给多个参数。所以,当然它们是不同的,但它们是紧密相连的语法概念,理解一个会让你理解另一个。
        • 就像我说的,它们是相关的,但鉴于提问者缺乏该领域的专业知识,这会让人困惑而不是指导。
        • 很公平。希望他能进一步挖掘。
        【解决方案5】:

        虽然这不是您提出的问题的答案,但它应该有所帮助。由于 zip 用于组合两个列表,因此您应该执行类似 list(zip(p[0], p[1])) 的操作来完成您所期望的。

        【讨论】:

          【解决方案6】:

          “*”运算符unpacks 一个列表并将其应用于函数。 zip 函数接受 n 个列表并从两个列表中的每个元素创建 n 元组对:

          zip([iterable, ...])

          这个函数返回一个元组列表,其中第 i 个元组包含 每个参数序列或迭代的第 i 个元素。这 返回列表的长度被截断为最短的长度 论据序列。当有多个参数都是 相同的长度,zip() 类似于 map(),初始参数为 没有。使用单个序列参数,它返回一个 1 元组列表。 没有参数,它返回一个空列表。

          基本上,通过使用*[[1,2,3],[4,5,6]],您将[1,2,3][4,5,6] 作为参数传递给zip。

          【讨论】:

            猜你喜欢
            • 2015-07-01
            • 2013-07-11
            • 2014-06-27
            • 1970-01-01
            • 1970-01-01
            • 2015-08-23
            • 1970-01-01
            • 2015-03-09
            • 1970-01-01
            相关资源
            最近更新 更多