¿Cómo se llama este tipo de asignación en Python? a = b = Verdadero

Sé sobre el desempaquetado de tuplas, pero ¿cómo se llama esta asignación donde tiene varios signos de igual en una sola línea? a la a = b = True

Siempre me sorprende un poco, especialmente cuando el RHS es mutable, pero estoy teniendo problemas para encontrar las palabras clave adecuadas para buscar en los documentos.

Es una cadena de tareas y el término usado para describirlo es …

– ¿Puedo conseguir un tambor por favor?

Asignación encadenada .


Acabo de dar una buena racha en Google y descubrí que no hay mucho que leer sobre el tema, probablemente ya que la mayoría de la gente lo encuentra muy sencillo de usar (y solo los verdaderos geeks desean saber más sobre el tema) .


En la expresión anterior, el orden de evaluación se puede ver comenzando en el extremo más a la derecha = y luego trabajando hacia la izquierda, lo que sería equivalente a escribir:

 b = True a = b 

El orden anterior es lo que la mayoría de los lenguajes describen una cadena de asignación , pero Python lo hace de manera diferente. En python, la expresión se evalúa como esto por debajo del equivalente, aunque no dará como resultado ningún otro resultado que el descrito anteriormente.

 temporary_expr_result = True a = temporary_expr_result b = temporary_expr_result 

Lecturas adicionales disponibles aquí en stackoverflow:

  • ¿Cómo funcionan las tareas encadenadas? python

OK, “asignación encadenada” era el término de búsqueda que buscaba, pero después de un poco más de investigación, creo que no es estrictamente correcto. pero es más fácil de buscar que “un caso especial de la statement de asignación”.

El artículo de Wikipedia Senderle vinculado a dice:

En Python, las instrucciones de asignación no son expresiones y, por lo tanto, no devuelven un valor. En su lugar, las asignaciones encadenadas son una serie de declaraciones con múltiples objectives para una sola expresión. Las asignaciones se ejecutan de izquierda a derecha, de modo que i = arr[i] = f() evalúa la expresión f() , luego asigna el resultado al objective más a la izquierda, i , y luego asigna el mismo resultado al siguiente objective, arr[i] , usando el nuevo valor de i .

Otra publicación del blog dice:

En Python, las instrucciones de asignación no devuelven un valor. La asignación encadenada (o más precisamente, el código que se parece a las declaraciones de asignación encadenada) se reconoce y se admite como un caso especial de la statement de asignación.

Esto me parece lo más correcto, en una lectura más detallada de los documentos , en particular (target_list "=")+ , que también dicen

Una statement de asignación evalúa la lista de expresiones … y asigna el único objeto resultante a cada una de las listas de destino, de izquierda a derecha.

Por lo tanto, realmente no se “evalúa de la derecha a la izquierda”, la RHS se evalúa y luego se asigna del objective de la izquierda a la derecha, no es que se me ocurran ejemplos en el mundo real (o incluso artificial) donde pueda diferencia.

La respuesta de @ refp es aún más compatible con esta salida utilizando el módulo de desassembly:

 >>> def a(x): ... g = h = x ... >>> import dis >>> dis.dis(a) 2 0 LOAD_FAST 0 (x) 3 DUP_TOP 4 STORE_FAST 1 (g) 7 STORE_FAST 2 (h) 10 LOAD_CONST 0 (None) 13 RETURN_VALUE 

El RHS se recupera y duplica, luego se almacena en las variables de destino de izquierda a derecha (inténtelo usted mismo con e = f = g = h = x ).

Algunos otros carteles se han confundido si el RHS es una llamada de función, como a = b = fn() : el RHS solo se evalúa una vez, y luego se asigna el resultado a cada variable sucesiva. Esto puede causar un intercambio no deseado si el valor devuelto es mutable, como una lista o dict.

Para aquellos que usan threading , es útil tener en cuenta que no hay una “atomicidad” implícita en el formulario de asignación encadenado sobre múltiples sentencias de asignación explícitas; Podrían ver valores diferentes en las dos variables.

De la documentación, 7.2. Enunciados de asignación , g y h son dos listas de objectives , siendo x la lista de expresiones :

 assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression) 

Una statement de asignación evalúa la lista de expresiones (recuerde que esto puede ser una expresión única o una lista separada por comas; esta última produce una tupla) y asigna el único objeto resultante a cada una de las listas de destino, de izquierda a derecha .

Me mordió la asignación encadenada de python hoy, debido a mi ignorancia. en codigo

 if l1.val <= l2.val: tail = tail.next = l1 # this line l1 = l1.next 

lo que esperaba era

 tail.next = l1 tail = tail.next # or equivalently # tail = l1 

mientras que obtuve a continuación, que produce un bucle automático en la lista, me deja en un bucle sin fin, gritos ...

 tail = l1 tail.next = l1 # now l1.next is changed to l1 itself 

ya que para a = b = c, una manera (python, por ejemplo) equivalente a

 tmp = evaluate(c) evaluate(a) = tmp evaluate(b) = tmp 

y tienen igual operando derecho para dos asignaciones.

el otro (C ++, por ejemplo) equivalente a

 evaluate(b) = evaluate(c) evaluate(a) = evaluate(b) 

ya que en este caso a = b = c es básicamente

 b = c a = b 

y dos operandos de la derecha podrían ser diferentes.

Es por eso que código similar funciona bien en C ++.