OK j'aime la fonction Zip()
de Python. Utilisez-le tout le temps, c'est génial. De temps en temps, je veux faire le contraire de Zip()
, penser «j’ai su comment faire cela», puis google python unzip, puis rappeler que l’on utilise ce *
magique pour décompresser une liste de tuples zippée. Comme ça:
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)
Qu'est-ce qui se passe? Que fait cet astérisque magique? Où peut-il être appliqué et quelles autres choses incroyables et impressionnantes dans Python sont si mystérieuses et difficiles à rechercher sur Google?
L'astérisque en Python est documenté dans le didacticiel Python, sous - Lister les listes d'arguments .
L'astérisque exécute apply
(comme il est connu dans LISP et Scheme). Fondamentalement, il prend votre liste et appelle la fonction avec le contenu de cette liste comme arguments.
C'est aussi utile pour plusieurs arguments:
def foo(*args):
print args
foo(1, 2, 3) # (1, 2, 3)
# also legal
t = (1, 2, 3)
foo(*t) # (1, 2, 3)
De plus, vous pouvez utiliser un double astérisque pour les arguments de mots clés et les dictionnaires:
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}
Et bien sûr, vous pouvez combiner ces éléments:
def foo(*args, **kwargs):
print args, kwargs
foo(1, 2, a=3, b=4) # (1, 2) {'a': 3, 'b': 4}
Des choses très soignées et utiles.
Ça ne marche pas toujours:
>>> 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
Oops! Je pense qu'il a besoin d'un crâne pour l'effrayer en travaillant:
>>> unzipped_x, unzipped_y = Zip(*zipped) or ([], [])
>>> unzipped_x
[]
>>> unzipped_y
[]
En python3 je pense que tu as besoin
>>> unzipped_x, unzipped_y = Tuple(Zip(*zipped)) or ([], [])
puisque Zip retourne maintenant une fonction génératrice qui n'est pas False-y.
Je suis extrêmement nouveau en Python, alors cela m’a tout récemment fait trébucher, mais il fallait en faire plus avec la façon dont l’exemple était présenté et ce qui était souligné.
Ce qui m'a posé des problèmes pour comprendre l'exemple Zip, c'est l'asymétrie dans le traitement des valeurs de retour d'appel Zip. C'est-à-dire que lorsque Zip est appelé pour la première fois, la valeur renvoyée est affectée à une seule variable, créant ainsi une référence à la liste (contenant la liste de Tuple créée). Dans le deuxième appel, il exploite la capacité de Python à décompresser automatiquement une liste (ou une collection?) En renvoyant une valeur renvoyée dans plusieurs références de variable, chaque référence étant le tuple individuel. Si quelqu'un ne sait pas comment cela fonctionne en Python, il est plus facile de se perdre pour savoir ce qui se passe réellement.
>>> 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
(x, y) == Tuple(Zip(*Zip(x,y)))
est vrai si et seulement si les deux déclarations suivantes sont vraies:
x
et y
ont la même longueurx
et y
sont des n-upletsUn bon moyen de comprendre ce qui se passe est d’imprimer à chaque étape:
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))))
Quelles sorties:
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')]
Fondamentalement, voici ce qui se passe:
x
et y
sont appariés en fonction de leurs index respectifs.(1, 2, 3)
('a', 'b', 'c')
Vous pouvez maintenant comprendre pourquoi (x, y) == Tuple(Zip(*Zip(x,y)))
est faux dans ce cas:
y
est plus long que x
, la première opération Zip a supprimé l'élément supplémentaire de y
(car il ne pouvait pas être apparié), ce changement est évidemment répercuté sur la deuxième opération de compression.Zip
fait la paire d'éléments dans les n-uplets et non dans les listesSi vous n'êtes pas sûr à 100% de comprendre le fonctionnement de Zip
, j’ai répondu ici à cette question: Décompression et opérateur *
Addendum à la réponse de @ bcherry:
>>> def f(a2,a1):
... print a2, a1
...
>>> d = {'a1': 111, 'a2': 222}
>>> f(**d)
222 111
Cela fonctionne donc non seulement avec les arguments de mots clés (dans ce sens strict ), mais aussi avec les arguments nommés (aka positional arguments).