我使用的是列表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)]
我发现在列表名称前添加'*'可以得到我所需的输出,但我无法弄清楚它们的操作差异。你能解释一下这个区别吗?
答案 0 :(得分:42)
zip
希望将一堆参数压缩在一起,但你拥有的是一个参数(一个列表,其元素也是列表)。函数调用中的*
"解包"列表(或其他可迭代的),使其每个元素成为单独的参数。因此,如果没有*
,您就会zip( [[1,2,3],[4,5,6]] )
。使用*
,您正在zip([1,2,3], [4,5,6])
。
答案 1 :(得分:9)
*
运算符在函数调用语句中解包参数。
考虑一下
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])
并获得预期的输出。
答案 2 :(得分:7)
*
字符称为解包运算符。当它出现在可迭代对象后面时,它所做的是将迭代中的项目逐个传递给函数的调用者。在这种情况下,由于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]
答案 3 :(得分:1)
虽然这不是您提出的问题的答案,但它应该有所帮助。由于zip用于组合两个列表,因此您应该执行类似list(zip(p[0], p[1]))
之类的操作来完成您期望的操作。
答案 4 :(得分:0)
简而言之,使用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个args传递给zip,因此你需要一个星形运算符。没有它,你只会传递一个参数。
答案 5 :(得分:0)