zip(list)和zip(*list)的区别

66

我使用了一个列表 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)]

我发现在列表名前加上 '*' 可以得到我想要的输出,但我不知道它们操作上的区别。你能解释一下吗?

6个回答

109

zip需要一堆参数来进行压缩在一起,但你只有一个参数(一个列表,其元素也是列表)。函数调用中的*会将列表(或其他可迭代对象)“解包”,使其每个元素成为单独的参数。因此,如果没有*,你执行的是zip([[1,2,3],[4,5,6]])。如果有*,你执行的是zip([1,2,3],[4,5,6])


4
关于展开运算符 *,这是我读过的最好的解释。谢谢。 - Antoine Colson

24
*运算符用于在函数调用语句中展开参数。
考虑下面的例子。
def add(x, y):
   return x + y

如果你有一个列表,你可以说,但这是不必要的冗长,你可以使用星号操作符将“解包”为单独的参数,如。
这就是你的示例中发生的事情。就像运行。在这里,zip只有一个参数,因此它简单地将其作为元组返回。 就像运行。这类似于运行,你会得到期望的输出。

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

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

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

另外请注意,自 Python-3.5 起,你可以在一些情况下使用打包操作符(unpacking operator),而不仅仅是函数调用。其中之一被称为“就地解包”(in-place unpacking),它允许你在另一个可迭代对象中使用解包。

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, 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]进行压缩,因此您需要传递两个参数给zip,因此需要使用星号运算符。如果没有它,您只传递一个参数。


1
一个带有 *** 的函数 定义 是使用 * 运算符的不同用法,就像你提到的那样。在这种情况下,它用于创建可变参数函数。它们与 OP 所说的 * 有关,后者更像是 apply 运算符的语法糖。混淆它们是个坏主意。 - Noufal Ibrahim
1
我认为它们是同一概念的两个方面(尽管是不同的行为)。在一个情况下(函数定义),您指定函数将接受一个名称(args)下分组的多个参数,而在另一个情况下,您使一个名称分派到多个参数。因此,它们当然是不同的,但它们是紧密联系的语法概念,理解其中一个可以帮助您理解另一个。 - vermillon
就像我所说的那样,它们是相关的,但考虑到提问者在这个领域缺乏专业知识,这会让他们感到困惑而不是得到指导。 - Noufal Ibrahim
好的,希望他能深入挖掘。 - vermillon

1

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


-1

星号运算符 解包 一个列表并将其应用于函数。zip 函数接受 n 个列表,并从两个列表的每个元素创建 n-元组对:

zip([iterable, ...])

此函数返回一个元组列表,其中第 i 个元组包含来自每个参数序列或可迭代对象的第 i 个元素。返回的列表被截断为最短参数序列的长度。当有多个参数都具有相同的长度时,zip() 类似于带有初始参数 None 的 map()。对于单个序列参数,它返回一个 1-元组列表。没有参数时,它返回一个空列表。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接