web-dev-qa-db-fra.com

astérisque dans l'appel de fonction

J'utilise itertools.chain pour "aplatir" une liste de listes de cette façon:

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

en quoi est-ce différent de dire:

uniqueCrossTabs = list(itertools.chain(uniqueCrossTabs))
105
Ramy

* Est l'opérateur "splat": il prend une liste en entrée et la développe en arguments positionnels réels dans l'appel de fonction.

Donc, si uniqueCrossTabs était [ [ 1, 2 ], [ 3, 4 ] ], Alors itertools.chain(*uniqueCrossTabs) revient à dire itertools.chain([ 1, 2 ], [ 3, 4 ])

C'est évidemment différent de passer juste uniqueCrossTabs. Dans votre cas, vous avez une liste de listes que vous souhaitez aplatir; ce que itertools.chain() fait, c'est 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 dans uniqueCrossTabs comme argument à chain(), qui les enchaînera, mais vous n'avez pas les listes dans des variables distinctes, vous utilisez donc l'opérateur * pour développer la liste de listes en plusieurs arguments de liste.

Comme Jochen Ritzel l'a souligné 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))
173
Cameron

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)
67

Juste une autre façon 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]
26
Gelbander