好的我喜欢Python的zip()
功能。一直使用它,它很棒。我一次又一次地想要做zip()
的反面,想想“我以前知道怎么做”,然后谷歌python解压缩,然后记住一个使用这个神奇的*
解压缩拉链元组列表。像这样:
x = [1,2,3]
y = [4,5,6]
zipped = zip(x,y)
unzipped_x, unzipped_y = zip(*zipped)
unzipped_x
Out[30]: (1, 2, 3)
unzipped_y
Out[31]: (4, 5, 6)
到底是怎么回事?那个神奇的星号在做什么?还有什么地方可以应用,Python中其他令人惊叹的精彩内容是如此神秘且难以谷歌?
答案 0 :(得分:39)
Python中的星号记录在Python教程的Unpacking Argument Lists下。
答案 1 :(得分:18)
星号执行apply
(在Lisp和Scheme中已知)。基本上,它接受您的列表,并使用该列表的内容作为参数调用该函数。
答案 2 :(得分:8)
它对多个args也很有用:
def foo(*args):
print args
foo(1, 2, 3) # (1, 2, 3)
# also legal
t = (1, 2, 3)
foo(*t) # (1, 2, 3)
并且,您可以对关键字参数和词典使用双星号:
def foo(**kwargs):
print kwargs
foo(a=1, b=2) # {'a': 1, 'b': 2}
# also legal
d = {"a": 1, "b": 2}
foo(**d) # {'a': 1, 'b': 2}
当然,你可以将这些结合起来:
def foo(*args, **kwargs):
print args, kwargs
foo(1, 2, a=3, b=4) # (1, 2) {'a': 3, 'b': 4}
非常整洁有用的东西。
答案 3 :(得分:6)
它并不总是有效:
>>> x = []
>>> y = []
>>> zipped = zip(x, y)
>>> unzipped_x, unzipped_y = zip(*zipped)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: need more than 0 values to unpack
糟糕!我认为它需要一个头骨才能吓跑它:
>>> unzipped_x, unzipped_y = zip(*zipped) or ([], [])
>>> unzipped_x
[]
>>> unzipped_y
[]
在python3中我认为你需要
>>> unzipped_x, unzipped_y = tuple(zip(*zipped)) or ([], [])
因为zip现在返回一个不是False-y的生成器函数。
答案 4 :(得分:2)
我对Python非常陌生,所以这最近才引起我的兴趣,但它必须更多地展示示例的呈现方式以及强调的内容。
让我理解zip示例的问题在于处理zip调用返回值的不对称性。也就是说,当第一次调用zip时,返回值将分配给单个变量,从而创建列表引用(包含创建的元组列表)。在第二个调用中,它利用Python的能力自动将列表(或集合?)返回值解包为多个变量引用,每个引用都是单个元组。如果有人不熟悉Python中的工作方式,那么就会更容易迷失实际发生的事情。
>>> x = [1, 2, 3]
>>> y = "abc"
>>> zipped = zip(x, y)
>>> zipped
[(1, 'a'), (2, 'b'), (3, 'c')]
>>> z1, z2, z3 = zip(x, y)
>>> z1
(1, 'a')
>>> z2
(2, 'b')
>>> z3
(3, 'c')
>>> rezipped = zip(*zipped)
>>> rezipped
[(1, 2, 3), ('a', 'b', 'c')]
>>> rezipped2 = zip(z1, z2, z3)
>>> rezipped == rezipped2
True
答案 5 :(得分:0)
@ bcherry答案的附录:
>>> def f(a2,a1):
... print a2, a1
...
>>> d = {'a1': 111, 'a2': 222}
>>> f(**d)
222 111
因此,它不仅可以使用关键字参数(在this strict sense中),还可以使用命名参数(也就是位置参数)。
答案 6 :(得分:0)
(x, y) == tuple(zip(*zip(x,y)))
为真,且仅当以下两个语句为真时:
x
和y
的长度相同x
和y
是元组了解发生了什么的一种好方法是在每个步骤打印:
x = [1, 2, 3]
y = ["a", "b", "c", "d"]
print("1) x, y = ", x, y)
print("2) zip(x, y) = ", list(zip(x, y)))
print("3) *zip(x, y) = ", *zip(x, y))
print("4) zip(*zip(x,y)) = ", list(zip(*zip(x,y))))
哪个输出:
1) x, y = [1, 2, 3] ['a', 'b', 'c', 'd']
2) zip(x, y) = [(1, 'a'), (2, 'b'), (3, 'c')]
3) *zip(x, y) = (1, 'a') (2, 'b') (3, 'c')
4) zip(*zip(x,y)) = [(1, 2, 3), ('a', 'b', 'c')]
基本上就是这样:
x
和y
的(1, 2, 3)
('a', 'b', 'c')
现在您可以了解为什么(x, y) == tuple(zip(*zip(x,y)))
在这种情况下为假:
y
比x
长,因此第一个zip操作从y
中删除了多余的项目(因为无法配对),因此显然在第二个项目上重新执行了此更改压缩操作zip
确实在元组而不是列表中配对项目如果您不确定100%地了解zip
的工作原理,那么我在这里写了一个对此问题的答案:Unzipping and the * operator