*
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 deciritertools.chain([ 1, 2 ], [ 3, 4 ])
Obviamente, esto es diferente a pasar solo uniqueCrossTabs
. En su caso, tiene una lista de listas que desea aplanar; quéitertools.chain()
hace es devolver un iterador sobre la concatenación de todos los argumentos posicionales que le pasas, donde cada argumento posicional es iterable por derecho propio.
En otras palabras, desea pasar cada lista uniqueCrossTabs
como un argumento a chain()
, lo 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, para empezar, asume un único iterable de iterables. Su código se convierte entonces en simplemente:
uniqueCrossTabs = list(itertools.chain.from_iterable(uniqueCrossTabs))