también debe verificar el **operador: hace lo mismo que *pero con argumentos de palabras clave.
Sean Vieira
Respuestas:
181
* 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 uniqueCrossTabsfue [ [ 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 uniqueCrossTabscomo 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:
@larsmans: Creo que el término es más popular en el mundo de Ruby, pero parece ser aceptable para Python también. Me gusta porque es divertido decirlo ;-)
Cameron
1
@larsmans: ¡Interesante! Siempre pensé que se refería a la acción de descomprimir la lista en una lista de argumentos, no al personaje en sí.
Cameron
1
Tal vez las cadenas no sean el mejor ejemplo porque no todos ven las cadenas como iterables. Por cierto: en lugar de chain(*it)escribir yo chain.from_iterable(it).
Jochen Ritzel
@Jochen: Tienes toda la razón, lo cambiaré para usar números. Además, ¡ni siquiera sabía que from_iterableexistía! Lo agregaré a mi respuesta en breve
Cameron
1
@Ramy: *es solo para expandir la lista en argumentos posicionales para una función (así que sí, muy específico). Puede hacer for l in uniqueCrossTabs:para iterar sobre ellos. Desafortunadamente, es difícil de ver *en el trabajo, ya que solo funciona cuando se pasa una lista a una función (en lugar de pasar la lista como el primer parámetro, *hace que cada elemento de la lista se pase como un parámetro separado, uno tras otro , como si se hubieran escrito separados por comas en la lista de parámetros)
Cameron
72
Divide la secuencia en argumentos separados para la llamada a la función.
>>>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)
esto es importante y no se menciona en ninguna otra parte
Gershom
1
Esta respuesta no se aplica a la pregunta específicamente, pero es una aplicación importante del asterisco (así que creo que es apropiado bajo el título bastante "nebuloso"). En la misma línea, otra aplicación importante está en las definiciones de funciones: def func(a, b, *args):consulte esta respuesta para obtener más información.
**
operador: hace lo mismo que*
pero con argumentos de palabras clave.Respuestas:
*
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 ] ]
, entoncesitertools.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 achain()
, 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:fuente
chain(*it)
escribir yochain.from_iterable(it)
.from_iterable
existía! Lo agregaré a mi respuesta en breve*
es solo para expandir la lista en argumentos posicionales para una función (así que sí, muy específico). Puede hacerfor l in uniqueCrossTabs:
para iterar sobre ellos. Desafortunadamente, es difícil de ver*
en el trabajo, ya que solo funciona cuando se pasa una lista a una función (en lugar de pasar la lista como el primer parámetro,*
hace que cada elemento de la lista se pase como un parámetro separado, uno tras otro , como si se hubieran escrito separados por comas en la lista de parámetros)Divide la secuencia en argumentos separados para la llamada a la función.
fuente
Solo una forma alternativa de explicar el concepto / usarlo.
fuente
def func(a, b, *args):
consulte esta respuesta para obtener más información.