135 votes

Astérisque dans l'appel de fonction

J'utilise itertools.chain pour "aplatir" une liste de listes de cette manière :

uniqueCrossTabs = list(itertools.chain(*uniqueCrossTabs))

en quoi est-ce différent que de dire :

uniqueCrossTabs = list(itertools.chain(uniqueCrossTabs))

9 votes

Jetez un coup d'œil à dépaquetage des listes d'arguments dans la documentation Python pour plus d'informations.

10 votes

vous devriez également consulter le ** opérateur -- il fait la même chose que * mais avec des arguments sous forme de mots-clés.

206voto

Cameron Points 32208

* est l'opérateur "splat" : Il prend une liste en entrée, et l'étend en arguments positionnels réels dans l'appel de fonction.

Donc si uniqueCrossTabs était [ [ 1, 2 ], [ 3, 4 ] ] alors itertools.chain(*uniqueCrossTabs) c'est la même chose que de dire itertools.chain([ 1, 2 ], [ 3, 4 ])

C'est évidemment différent que de passer dans juste uniqueCrossTabs . Dans votre cas, vous disposez d'une liste de listes que vous souhaitez aplatir. itertools.chain() retourne un itérateur sur la concaténation de tous les arguments positionnels que vous lui passez, où chaque argument positionnel est itérable en soi.

En d'autres termes, vous voulez passer chaque liste en uniqueCrossTabs en tant qu'argument pour chain() qui les enchaînera, mais vous n'avez pas les listes dans des variables séparées, donc vous utilisez la fonction * pour développer la liste des listes en plusieurs arguments de liste.

Comme l'a souligné Jochen Ritzel dans les commentaires, chain.from_iterable() est mieux adapté à cette opération, car il suppose un seul itérable d'itérables pour commencer. Votre code devient alors simplement :

uniqueCrossTabs = list(itertools.chain.from_iterable(uniqueCrossTabs))

9 votes

@larsmans : Je pense que le terme est plus populaire dans le monde Ruby, mais il semble être acceptable pour Python aussi Je l'aime parce que c'est amusant à dire ;-)

1 votes

@larsmans : Intéressant ! J'ai toujours pensé que cela faisait référence à l'action de déballer la liste en une liste d'arguments, et non au caractère lui-même.

1 votes

Les chaînes de caractères ne sont peut-être pas le meilleur exemple, car tout le monde ne considère pas les chaînes de caractères comme des itérables. Btw : Au lieu de chain(*it) J'écrirais chain.from_iterable(it) .

83voto

Il divise la séquence en arguments séparés pour l'appel de fonction.

>>> def foo(a, b=None, c=None):
...   print a, b, c
... 
>>> foo([1, 2, 3])
[1, 2, 3] None None
>>> foo(*[1, 2, 3])
1 2 3
>>> def bar(*a):
...   print a
... 
>>> bar([1, 2, 3])
([1, 2, 3],)
>>> bar(*[1, 2, 3])
(1, 2, 3)

32voto

gelbander Points 1138

C'est juste une façon alternative d'expliquer le concept/de l'utiliser.

import random

def arbitrary():
    return [x for x in range(1, random.randint(3,10))]

a, b, *rest = arbitrary()

# a = 1
# b = 2
# rest = [3,4,5]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X