python python-3.x iterable-unpacking

plot title python



ComprensiĆ³n*x,=lst (3)

Es una característica que se introdujo en Python 3.0 ( python.org/dev/peps/pep-3132 ). En Python 2, podrías hacer algo como esto:

>>> p = [1, 2, 3] >>> q, r, s = p >>> q 1 >>> r 2 >>> s 3

Python 3 extendió esto para que una variable pueda contener múltiples valores:

>>> p = [1, 2, 3] >>> q, *r = p >>> q 1 >>> r [2, 3]

Esto, por lo tanto, es lo que se está utilizando aquí. Sin embargo, en lugar de dos variables para contener tres valores, es solo una variable que toma cada valor en la lista. Esto es diferente de x = p porque x = p solo significa que x es otro nombre para p . En este caso, sin embargo, es una lista nueva que simplemente tiene los mismos valores. (Puede que le interese "Asombro mínimo" y el argumento predeterminado mutable )

Otras dos formas comunes de producir este efecto son:

>>> x = list(p)

y

>>> x = p[:]

Desde Python 3.3, el objeto de lista en realidad tiene un método destinado a copiar:

x = p.copy()

La rebanada es en realidad un concepto muy similar. Sin embargo, como señaló nneonneo, eso solo funciona con objetos como listas y tuplas que admiten cortes. Sin embargo, el método que menciona funciona con cualquier iterable: diccionarios, conjuntos, generadores, etc.

Estoy revisando un código antiguo tratando de entender lo que hace, y me encontré con esta extraña declaración:

*x ,= p

p es una lista en este contexto. He estado tratando de averiguar qué hace esta declaración. Por lo que puedo decir, solo establece x en el valor de p . Por ejemplo:

p = [1,2] *x ,= p print(x)

Solo da

[1, 2]

Entonces, ¿es esto diferente de x = p ? ¿Alguna idea de lo que está haciendo esta sintaxis?


Siempre debes tirarlos a la dis y ver qué te devuelve; verá cómo *x, = p es realmente diferente de x = p :

dis(''*x, = p'') 1 0 LOAD_NAME 0 (p) 2 UNPACK_EX 0 4 STORE_NAME 1 (x)

Mientras, la declaración de asignación simple:

dis(''x = p'') 1 0 LOAD_NAME 0 (p) 2 STORE_NAME 1 (x)

(Eliminación de None no relacionado devuelve)

Como puede ver, UNPACK_EX es el código de UNPACK_EX diferente entre estos; está documentado como :

Implementa la asignación con un objetivo destacado: desempaqueta un iterable en TOS (parte superior de la pila) en valores individuales, donde el número total de valores puede ser menor que el número de elementos en el iterable: uno de los nuevos valores será una lista de todos artículos sobrantes.

Es por eso que, como señaló Eugene, obtienes un nuevo objeto al que se hace referencia con el nombre x y no una referencia a un objeto ya existente (como es el caso con x = p ).

*x, parece muy extraño (la coma extra allí y todo) pero se requiere aquí. El lado izquierdo debe ser una tupla o una lista y, debido a la peculiaridad de crear una tupla de un solo elemento en Python, debe usar un final:

i = 1, # one element tuple

Si te gusta confundir a las personas, siempre puedes usar la versión de list de esto:

[*x] = p

que hace exactamente lo mismo pero no tiene esa coma extra por ahí.


*x ,= p es básicamente una versión ofuscada de x = list(p) utiliza python.org/dev/peps/pep-3132 . La coma después de x es necesaria para hacer que la asignación se convierta en una tupla (aunque también podría ser una lista).

*x, = p es diferente de x = p porque el primero crea una copia de p (es decir, una nueva lista) mientras que el segundo crea una referencia a la lista original. Para ilustrar:

>>> p = [1, 2] >>> *x, = p >>> x == p True >>> x is p False >>> x = p >>> x == p True >>> x is p True