*
é o operador "splat": ele pega uma lista como entrada e a expande em argumentos posicionais reais na chamada de função.
Então, se uniqueCrossTabs
fosse [ [ 1, 2 ], [ 3, 4 ] ]
, itertools.chain(*uniqueCrossTabs)
é o mesmo que dizeritertools.chain([ 1, 2 ], [ 3, 4 ])
Isso é obviamente diferente de passar apenas uniqueCrossTabs
. No seu caso, você tem uma lista de listas que deseja simplificar; o que itertools.chain()
faz é retornar um iterador sobre a concatenação de todos os argumentos posicionais que você passa para ele, onde cada argumento posicional é iterável por si só.
Em outras palavras, você deseja passar cada lista uniqueCrossTabs
como um argumento para chain()
, o que as encadeará, mas você não tem as listas em variáveis separadas, então você usa o *
operador para expandir a lista de listas em vários argumentos de lista.
Como Jochen Ritzel apontou nos comentários, chain.from_iterable()
é mais adequado para esta operação, pois assume um único iterável de iteráveis para começar. Seu código se torna simplesmente:
uniqueCrossTabs = list(itertools.chain.from_iterable(uniqueCrossTabs))