Python zip(列表)和zip(*列表)之间的差异
我正在使用一个列表Python zip(列表)和zip(*列表)之间的差异,python,python-3.x,Python,Python 3.x,我正在使用一个列表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)] 我发现在列表名之前添加一个“*”可以提供我所需的输出,但我无法区分它们的操作。你能解释一下区别吗?虽然这不是
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)]
我发现在列表名之前添加一个“*”可以提供我所需的输出,但我无法区分它们的操作。你能解释一下区别吗?虽然这不是你所问问题的答案,但应该会有所帮助。由于zip用于组合两个列表,因此您应该执行类似于以下的操作来完成预期的操作。
zip
希望将一组参数压缩在一起,但您只有一个参数(列表,其元素也是列表)。函数调用中的*
将列表(或其他iterable)“解包”,使其每个元素成为单独的参数。因此,如果没有*
,您就在做zip([[1,2,3],[4,5,6]])
。使用*
,您正在执行zip([1,2,3],[4,5,6])
简而言之,使用x=[1,2,3]
,调用f(x)
时,x接收1个参数[1,2,3]
。使用星形运算符f(*x)
时,f接收三个参数,它相当于调用f(1,2,3)
这就是为什么在Python文档中,您经常会看到一些函数(*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,因此您需要一个星形运算符。没有它,您只传递一个参数。字符
*
称为解包运算符。当它出现在iterable对象后面时,它所做的是将iterable中的项逐个传递给函数的调用方。在这种情况下,由于zip
函数接受一个iterables列表以返回对齐的列,zip(*p)
将p
中的所有项目作为参数传递给zip
函数:
因此,在这种情况下,zip(*p)
等于:
zip([1,2,3],[4,5,6])
另外,请注意,由于Python-3.5,您可以在函数调用程序之外的一些其他情况下使用解包运算符。其中之一称为就地解包,允许您在另一个iTable中使用解包
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]
*
运算符在函数调用语句中解压参数
想想这个
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])
并获得预期的输出 运算符“*”创建列表并将其应用于函数。该函数获取n个列表,并从两个列表中的每个元素创建n元组对:
zip([iterable,…])
此函数返回元组列表,其中第i个元组包含
每个参数序列或iterables的第i个元素。这个
返回的列表的长度被截断为最短列表的长度
参数序列。当有多个参数都是
相同的长度,zip()类似于map(),初始参数为
没有一个对于单个序列参数,它返回一个1元组列表。
如果没有参数,它将返回一个空列表
基本上,通过将
*
与[[1,2,3],[4,5,6]
一起使用,您将[1,2,3]
和[4,5,6]
作为zip的参数进行传递。像您提到的那样使用*
或***
的函数定义是*
操作符的不同用法。在这种情况下,它用于创建。它们与OP所说的*
有关,后者更像是apply
操作符的语法糖。混淆两者是个坏主意。我认为它们是同一概念的两个方面(尽管行为不同)。在一种情况下(函数定义),指定函数将接受在一个名称(args)下分组的多个参数,而在另一种情况下,将一个名称分派给多个参数。当然,它们是不同的,但它们是紧密相连的语法概念,理解其中一个会让你理解另一个。就像我说的,它们是相关的,但考虑到提问者缺乏这方面的专业知识,这会让人困惑,而不是指导。这很公平。希望他能进一步挖掘。我读过的关于解包操作员的最好解释*
。非常感谢。