vous devriez également vérifier l' **opérateur - il fait la même chose que *mais avec des arguments de mot-clé.
Sean Vieira
Réponses:
181
* est l'opérateur "splat": il prend une liste comme entrée et l'étend en arguments positionnels réels dans l'appel de fonction.
Donc si uniqueCrossTabsc'était le cas [ [ 1, 2 ], [ 3, 4 ] ], alors itertools.chain(*uniqueCrossTabs)c'est la même chose que de direitertools.chain([ 1, 2 ], [ 3, 4 ])
C'est évidemment différent du passage juste uniqueCrossTabs. Dans votre cas, vous avez une liste de listes que vous souhaitez aplatir; ce qui itertools.chain()fait est de retourner un itérateur sur la concaténation de tous les arguments positionnels que vous lui passez, où chaque argument positionnel est itérable à part entière.
En d'autres termes, vous voulez passer chaque liste en uniqueCrossTabstant qu'argument à chain(), ce qui les enchaînera, mais vous n'avez pas les listes dans des variables séparées, vous utilisez donc le* opérateur pour développer la liste des listes en plusieurs arguments de liste.
Comme Jochen Ritzel l'a souligné dans les commentaires, chain.from_iterable()est mieux adapté pour cette opération, car elle suppose un seul itérable d'itérables pour commencer. Votre code devient alors simplement:
@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 ;-)
Cameron
1
@larsmans: Intéressant! J'ai toujours pensé que cela faisait référence à l'action de décompresser la liste dans une liste d'arguments, pas au personnage lui-même.
Cameron
1
Peut-être que les chaînes ne sont pas le meilleur exemple car tout le monde ne voit pas les chaînes comme des itérables. Btw: Au lieu d' chain(*it)écrire chain.from_iterable(it).
Jochen Ritzel
@Jochen: Vous avez absolument raison, je vais le changer pour utiliser des nombres à la place. De plus, je ne savais même pas qu'il from_iterableexistait! Je vais l'ajouter dans ma réponse sous peu
Cameron
1
@Ramy: *sert uniquement à décomposer la liste en arguments positionnels vers une fonction (donc oui, très spécifique). Vous pouvez faire for l in uniqueCrossTabs:pour les parcourir. Malheureusement, c'est difficile à voir *au travail car cela ne fonctionne que lorsque vous passez une liste à une fonction (au lieu de passer la liste comme premier paramètre, *fait passer chaque élément de la liste en tant que paramètre séparé, l'un après l'autre , comme s'ils avaient été tapés séparés par des virgules dans la liste des paramètres)
Cameron
72
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]NoneNone>>> foo(*[1,2,3])123>>>def bar(*a):...print a
...>>> bar([1,2,3])([1,2,3],)>>> bar(*[1,2,3])(1,2,3)
Cette réponse ne s'applique pas spécifiquement à la question, mais est une application importante de l'astérisque (donc je pense qu'elle est appropriée sous le titre plutôt «brumeux»). Dans le même ordre d'idées, une autre application importante concerne les définitions de fonctions: def func(a, b, *args):consultez cette réponse pour plus d'informations.
**
opérateur - il fait la même chose que*
mais avec des arguments de mot-clé.Réponses:
*
est l'opérateur "splat": il prend une liste comme entrée et l'étend en arguments positionnels réels dans l'appel de fonction.Donc si
uniqueCrossTabs
c'était le cas[ [ 1, 2 ], [ 3, 4 ] ]
, alorsitertools.chain(*uniqueCrossTabs)
c'est la même chose que de direitertools.chain([ 1, 2 ], [ 3, 4 ])
C'est évidemment différent du passage juste
uniqueCrossTabs
. Dans votre cas, vous avez une liste de listes que vous souhaitez aplatir; ce quiitertools.chain()
fait est de retourner un itérateur sur la concaténation de tous les arguments positionnels que vous lui passez, où chaque argument positionnel est itérable à part entière.En d'autres termes, vous voulez passer chaque liste en
uniqueCrossTabs
tant qu'argument àchain()
, ce qui les enchaînera, mais vous n'avez pas les listes dans des variables séparées, vous utilisez donc le*
opérateur pour développer la liste des listes en plusieurs arguments de liste.Comme Jochen Ritzel l'a souligné dans les commentaires,
chain.from_iterable()
est mieux adapté pour cette opération, car elle suppose un seul itérable d'itérables pour commencer. Votre code devient alors simplement:la source
chain(*it)
écrirechain.from_iterable(it)
.from_iterable
existait! Je vais l'ajouter dans ma réponse sous peu*
sert uniquement à décomposer la liste en arguments positionnels vers une fonction (donc oui, très spécifique). Vous pouvez fairefor l in uniqueCrossTabs:
pour les parcourir. Malheureusement, c'est difficile à voir*
au travail car cela ne fonctionne que lorsque vous passez une liste à une fonction (au lieu de passer la liste comme premier paramètre,*
fait passer chaque élément de la liste en tant que paramètre séparé, l'un après l'autre , comme s'ils avaient été tapés séparés par des virgules dans la liste des paramètres)Il divise la séquence en arguments séparés pour l'appel de fonction.
la source
Juste une manière alternative d'expliquer le concept / de l'utiliser.
la source
def func(a, b, *args):
consultez cette réponse pour plus d'informations.