我用一个列表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是用来组合两个列表的,所以你应该做这样的事情,如list(zip(p[0], p[1]))
来完成你所期望的事情。
zip
想要一堆参数一起压缩,但你拥有的是一个参数(一个列表,其元素也是列表)。函数调用中的*
“解包”列表(或其他迭代),使其每个元素成为单独的参数。所以没有*
,你在做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的文档中,您经常会看到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
函数接受的迭代,你可以将多个迭代这个功能列表:
所以*p
结果是:
[1,2,3],[4,5,6]
和zip(*p)
等于zip([1,2,3],[4,5,6])
。
也为更好地了解需要注意的是*
可以用来解压缩列表:
>>> zip(*zip(*p))
[(1, 2, 3), (4, 5, 6)]
上面的命令解压的zip(*p)
的结果,所以你必须:
zip((1, 4), (2, 5), (3, 6))
该函数返回一个元组列表,其中第i个元组包含来自每个参数序列或迭代的第i个元素。返回的列表的长度被截断为最短参数序列的长度。当有多个长度相同的参数时,zip()类似于map(),初始参数为None。使用单个序列参数,它将返回1元组列表。没有参数,它返回一个空列表。
*
操作符在函数调用语句中解压参数。
考虑这个
def add(x, y):
return x + y
,如果你有一个列表t = [1,2]
,你可以说add(t[0], t[1])
这是不必要的冗长,或者您可以使用*
运营商,像这样add(*t)
“解压” 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])
类似,您可以获得预期的输出。
函数*定义*与'*'或'**'类似,您提到的是'*'运算符的不同用法。在这种情况下,它被用来创建[variadic functions](http://en.wikipedia.org/wiki/Variadic_function)。它们与OP正在讨论的'*'有关,它更像是'apply'操作符的语法糖。混淆两者是一个坏主意。 – 2015-03-19 07:56:59
我认为他们是同一概念的两个方面(尽管不同的行为)。在一种情况下(函数定义),您可以指定该函数将接受以一个名称(args)分组的多个参数,而在另一个情况下,您将一个名称分派给多个参数。所以,它们当然是不同的,但是它们紧密相连的语法概念和理解能力让你了解另一个。 – vermillon 2015-03-19 08:04:24
就像我说的,他们是相关的,但由于提问者缺乏该领域的专业知识,这会混淆而不是指导。 – 2015-03-19 08:45:23