Digamos que tenemos esto
>>> x = {'a': 1, 'b': 2} >>> y = {} >>> for k, y[k] in x.items(): pass ... >>> y {'a': 1, 'b': 2}¿Por qué funciona esto?
Nota: vi esto primero aquí
a, b = (c, d) desempaqueta la tupla de izquierda a derecha y asigna a = c y b = d en ese orden.
x.items() itera sobre pares clave-valor en x . Por ejemplo, hacer list(x.items()) dará [('a', 1), ('b', 2)]
for a, b in x.items() asigna la clave a a y el valor a b para cada par clave-valor en x .
for k, y[k] in x.items() asigna la clave a k y el valor a y[k] para cada par clave-valor en x .
Puede usar k en y[k] porque k ya ha sido asignado ya que el desempaquetado ocurre de izquierda a derecha
No necesita hacer nada en el bucle porque todo lo que necesitaba ya está hecho.
Debido a que el ciclo ya asignó cada valor en x a y[k] , y ahora es una copia superficial de x .
Como dice el tweet al que hace referencia, esta es de hecho una forma "concisa, poco intuitiva y confusa" de hacer x.copy()
Esta es una forma notablemente extraña de usar el enlace de bucle. Para cada elemento, la tupla de (key, value) se asigna a k, y[k] . Ambas instancias de k se refieren a la misma variable, por lo que la suscripción y[k] se asigna al diccionario y . Esto se basa en una tarea de desestructuración que se resuelve de izquierda a derecha; usando y[k], k no funciona ya que k no se asigna la primera vez a través del ciclo.
A la variable de iteración se le asignan valores a medida que itera a través del iterable. En su caso, k, y[k] se asignan con (key, value) de dict.items() .
En su caso y[k] en realidad llama a dict.__setitem__ aquí, por lo que su y se actualiza.
Ejemplo,
class T(): def __setitem__(self, key, value): print(f"Assigning {key} with value {value}") x = {"a": 2, "b": 3, "c": 4} val = T() for k, val[k] in x.items(): pass Assigning a with value 2 Assigning b with value 3 Assigning c with value 4 En su caso, se llama a dict.__setitem__ mientras itera a través x.items() y dict.__setitem__ muta su dict y , por lo que eventualmente está copiando x dict en y .
x = {'a': 2, 'b': 3, 'c': 4} it = iter(x.items()) y = {} [*iter(lambda : y.__setitem__(*next(it)), "Is this confusing enough??")] print(y) # {'a': 2, 'b': 3, 'c': 4}