logical - python// operator double slash
niebla en asterisco en python (3)
Estoy usando itertools.chain para "aplanar" una lista de listas de esta manera:
uniqueCrossTabs = list(itertools.chain(*uniqueCrossTabs))
¿Cómo es esto diferente a decir:
uniqueCrossTabs = list(itertools.chain(uniqueCrossTabs))
Divide la secuencia en argumentos separados para la llamada de función.
>>> 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)
Solo una forma alternativa de explicar el concepto / usarlo.
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]
*
es el operador "splat": toma una lista como entrada y la expande en argumentos posicionales reales en la llamada a la función.
Entonces, si uniqueCrossTabs
fue [ [ 1, 2 ], [ 3, 4 ] ]
, entonces itertools.chain(*uniqueCrossTabs)
es lo mismo que decir itertools.chain([ 1, 2 ], [ 3, 4 ])
Esto es obviamente diferente de pasar en uniqueCrossTabs
. En su caso, tiene una lista de listas que desea aplanar; lo que itertools.chain()
hace es devolver un iterador sobre la concatenación de todos los argumentos posicionales que le pasa, donde cada argumento posicional es iterable por derecho propio.
En otras palabras, quiere pasar cada lista en uniqueCrossTabs
como argumento a chain()
, que los encadenará, pero no tiene las listas en variables separadas, por lo que usa el operador *
para expandir la lista de listas en varios argumentos de lista.
Como Jochen Ritzel ha señalado en los comentarios, chain.from_iterable()
es más adecuado para esta operación, ya que supone un único iterable de iterables para comenzar. Su código se vuelve simple:
uniqueCrossTabs = list(itertools.chain.from_iterable(uniqueCrossTabs))