2010-03-13 12 views
30

Supongo que el siguiente código inicializaría los diccionarios dict_a, dict_b y dict_c. Pero las costuras de tener una copia a través del efecto:Copia de Python a través de la asignación?

dict_a = dict_b = dict_c = {} 
dict_c['hello'] = 'goodbye' 

print dict_a 
print dict_b 
print dict_c 

Como se puede ver el resultado es el siguiente:

{'hello': 'goodbye'} 
{'hello': 'goodbye'} 
{'hello': 'goodbye'} 

¿Por qué ese programa da el resultado anterior, en el que se puede esperar que vuelva :

{} 
{} 
{'hello': 'goodbye'} 
+0

Sin tutorial, sólo estaba aplicando conceptos pensé trabajado en lenguajes como Java . –

Respuesta

30

Esto se debe a que en Python, las variables (nombres) son solo referencias a objetos individuales. Cuando asigna dict_a = dict_b, realmente está copiando una dirección de memoria (o un puntero, si lo desea) de dict_b a dict_a. Todavía hay una instancia de ese diccionario.

Para obtener el comportamiento deseado, utilice el método dict.copy, o use copy.deepcopy si su dict puede haber anidado dicts u otros objetos anidados.

>>> a = {1:2} 
>>> b = a.copy() 
>>> b 
{1: 2} 
>>> b[3] = 4 
>>> a 
{1: 2} 
>>> b 
{1: 2, 3: 4} 
>>> 
+0

Así que los diccionarios son objetos, ¿seguiría siendo así con decir una variable entera o el tipo de una variable no tendría ningún impacto en que sea un objeto? –

+0

Los enteros son inmutables, por lo que no estoy seguro de cómo intenta reproducir este comportamiento. En cualquier caso, los valores literales para algunos tipos están internados (es decir, hay solo una instancia de cada uno). Puede verificar que dos variables enteras que contienen el mismo valor apuntan a la misma instancia del entero a través de la función 'id()'. – danben

+1

En cualquier caso, todo en Python es un objeto. Para ver las funciones que pertenecen al objeto entero 1, puede ejecutar 'dir (1)'. – danben

1

Su primera asignación asigna el mismo objeto diccionario para las variables dict_a, dict_b y dict_c. Es equivalente a dict_c = {}; dict_b = dict_c; dict_a = dict_c.

2

Como dijera previamente Danben, solo estás copiando el mismo diccionario en 3 variables, de modo que cada una se refiera al mismo objeto.

Para obtener el comportamiento que desea, usted debe instanciar un diccionario diferente en cada variable:

>>> dict_a, dict_b, dict_c = {}, {}, {} 
>>> dict_c['hello'] = 'goodbye' 
>>> print dict_a 
{} 
>>> print dict_b 
{} 
>>> print dict_c 
{'hello': 'goodbye'} 
>>> 
+0

Gracias, esto era lo que tenía la intención de hacer cuando tropecé con este tema. Aunque no es una respuesta a la pregunta, muchas gracias. –

8

Aunque

>>> dict_a, dict_b, dict_c = {}, {}, {} 

es el camino correcto a seguir en la mayoría de los casos, cuando consigue más de 3 se ve raro

Imagínese

>>> a, b, c, d, e, f = {}, {}, {}, {}, {}, {} 

En los casos en que quiero inicializar más de 3 cosas, yo uso

>>> a, b, c, d, e, f, = [dict() for x in range(6)] 

Precaución: No utilice [{} for x in range(6)]

+3

"Precaución: No use [{} para x en el rango (6)]" ¿Por qué no? la expresión del elemento se ejecuta una vez para cada iteración, y cada vez que se ejecuta un literal '{}', devuelve un nuevo dict. De hecho, esto debería preferirse a 'dict()' ya que evita una llamada a función. – SingleNegationElimination

+0

@TokenMacGuy, sí y no. Ahora que volví a leer lo que escribí, veo tu punto. '{}' se inicializa todo el tiempo. Dicho eso '{}' es solo una sintaxis de azúcar para 'dict()'. No estás guardando nada usando el anterior. –

+5

Jeffrey Jose: ¿Dudando de Thomas aye? 'importar dis; imprimir dis.dis (lambda: dict()); imprima dis.dis (lambda: {}) ' – SingleNegationElimination

Cuestiones relacionadas