关于python:zip(list)和zip(* list)之间的区别

Difference between zip(list) and zip(*list)

本问题已经有最佳答案,请猛点这里访问。

我用的是清单p = [[1,2,3],[4,5,6]]

如果我这样做:

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

不过,我真正想要的是通过以下方式获得:

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

我发现在列表名称之前添加一个"*"会给出我所需的输出,但我无法区分它们的操作。你能解释一下区别吗?


zip希望将一系列参数压缩在一起,但您拥有的是一个参数(一个列表,其元素也是列表)。函数调用中的*将列表(或其他iterable)"解包",使其每个元素都成为单独的参数。所以如果没有*,你就是在做zip( [[1,2,3],[4,5,6]] )。使用*时,您将使用zip([1,2,3], [4,5,6])


*运算符在函数调用语句中解包参数。

考虑这个

1
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]),您可以得到预期的输出。


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

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

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

另外,请注意,由于python-3.5,除了在函数调用程序中,在其他一些情况下,您可以对运算符进行解包。其中一个称为就地解包,它允许您在另一个iterable中使用解包。

1
2
3
4
5
6
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]

虽然这不是你问的问题的答案,但应该有帮助。因为zip用于组合两个列表,所以您应该像这样做list(zip(p[0], p[1]))来完成您所期望的。


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

zip([iterable, ...])

This function returns a list of tuples, where the i-th tuple contains
the i-th element from each of the argument sequences or iterables. The
returned list is truncated in length to the length of the shortest
argument sequence. When there are multiple arguments which are all of
the same length, zip() is similar to map() with an initial argument of
None. With a single sequence argument, it returns a list of 1-tuples.
With no arguments, it returns an empty list.

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


简言之,使用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时,实际上您希望使用[4,5,6]压缩[1,2,3],因此您希望将2个参数传递给zip,因此需要一个星形运算符。没有它,你只传递一个参数。