você também deve verificar o **operador - ele faz a mesma coisa, *mas com argumentos de palavra-chave.
Sean Vieira
Respostas:
181
* é o operador "splat": ele pega uma lista como entrada e a expande em argumentos posicionais reais na chamada de função.
Então, se uniqueCrossTabsfosse [ [ 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 uniqueCrossTabscomo 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:
@larsmans: Eu acho que o termo é mais popular no mundo Ruby, mas parece ser aceitável para Python também. Eu gosto porque é divertido de dizer ;-)
Cameron,
1
@larsmans: Interessante! Sempre pensei que se referia à ação de desempacotar a lista em uma lista de argumentos, não ao próprio personagem em si.
Cameron,
1
Talvez as strings não sejam o melhor exemplo, porque nem todo mundo vê as strings como iteráveis. A propósito: em vez de chain(*it)escrever chain.from_iterable(it).
Jochen Ritzel,
@Jochen: Você está absolutamente certo, vou mudá-lo para usar números. Além disso, eu nem sabia que from_iterableexistia! Vou adicioná-lo à minha resposta em breve
Cameron,
1
@Ramy: *serve apenas para explodir a lista em argumentos posicionais para uma função (então sim, muito específico). Você pode fazer for l in uniqueCrossTabs:para iterar sobre eles. Infelizmente é difícil ver *em funcionamento, pois só funciona quando você está passando uma lista para uma função (em vez de passar a lista como o primeiro parâmetro, *faz com que cada elemento na lista seja passado como um parâmetro separado, um após o outro , como se tivessem sido digitados separados por vírgulas na lista de parâmetros)
Cameron,
72
Ele divide a sequência em argumentos separados para a chamada de função.
>>>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)
Esta resposta não se aplica à pergunta especificamente, mas é uma aplicação importante do asterisco (portanto, acho que é apropriado para o título um tanto "nebuloso"). Na mesma linha, outra aplicação importante é nas definições de funções: def func(a, b, *args):Veja esta resposta para mais informações.
**
operador - ele faz a mesma coisa,*
mas com argumentos de palavra-chave.Respostas:
*
é 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 queitertools.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 parachain()
, 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:fonte
chain(*it)
escreverchain.from_iterable(it)
.from_iterable
existia! Vou adicioná-lo à minha resposta em breve*
serve apenas para explodir a lista em argumentos posicionais para uma função (então sim, muito específico). Você pode fazerfor l in uniqueCrossTabs:
para iterar sobre eles. Infelizmente é difícil ver*
em funcionamento, pois só funciona quando você está passando uma lista para uma função (em vez de passar a lista como o primeiro parâmetro,*
faz com que cada elemento na lista seja passado como um parâmetro separado, um após o outro , como se tivessem sido digitados separados por vírgulas na lista de parâmetros)Ele divide a sequência em argumentos separados para a chamada de função.
fonte
Apenas uma forma alternativa de explicar o conceito / utilizá-lo.
fonte
def func(a, b, *args):
Veja esta resposta para mais informações.