Python: Diccionario como variable de instancia [duplicado]

Posible duplicado:
"Menos asombro" en Python: el argumento predeterminado mutable

Estoy muy confundido acerca del comportamiento de los diccionarios como variables de instancia de clase en Python 3. De la forma en que lo entiendo, las variables de instancia en Python tienen por instancia almacenamiento, a diferencia de las variables de clase que son por clase (similar a lo que otros lenguajes llaman "estático").

Y esto parece ser cierto, excepto cuando la variable de instancia es un diccionario creado a partir de un parámetro predeterminado. Por ejemplo:

class Foo:
    def __init__(self, values = dict()):
        self.values = values

f1 = Foo()
f1.values["hello"] = "world"

f2 = Foo()
print(f2.values)

Este programa produce:

{'hello': 'world'}

¿Eh? ¿Por qué la instancia f2 tener la misma instancia de diccionario que f1?

Obtengo el comportamiento esperado si no paso un diccionario vacío como parámetro predeterminado, y simplemente asigno self.values a un diccionario vacío explícitamente:

class Foo:
    def __init__(self):
        self.values = dict()

Pero no veo por qué esto debería hacer alguna diferencia.

preguntado el 16 de mayo de 11 a las 17:05

Puede ser que los parámetros predeterminados solo se evalúen una vez, cuando se carga la clase. De esa manera, simplemente asigna la misma referencia como parámetro predeterminado. -

El desbordamiento de pila tiene una buena función de "Preguntas frecuentes" por etiqueta. Aquí están las preguntas frecuentes de la etiqueta Python: stackoverflow.com/questions/tagged/… Su pregunta se responde en la pregunta número 4. -

2 Respuestas

Esta es una sorpresa bien conocida en Python. Los parámetros predeterminados se evalúan cuando se define la función, no cuando se llama. Entonces, su parámetro predeterminado es una referencia a un dict. No tiene nada que ver con asignarlo a variables de clase / instancia.

Si desea utilizar un parámetro predeterminado, utilice Noney compruébalo:

if values is None:
    self.values = {}
else:
    self.values = values

contestado el 16 de mayo de 11 a las 21:05

Obtendrá el mismo comportamiento con una lista también: Jaydel

Obtienes el mismo comportamiento con cada uno objeto mutable. - usuario395760

Los valores predeterminados solo se evalúan una vez. Quieres algo como esto:

 class Foo:
     def __init__(self, values = None):
         self.values = values or dict()

Si proporciona un values, eso se acostumbrará. Si no, values se evalúa como FALSE mediante el or operador y crea una instancia de un nuevo dict.

contestado el 16 de mayo de 11 a las 21:05

Esto falla si se pasa algo falso como valores, por ejemplo, una instancia vacía de un archivo personalizado. dict subclase. - usuario395760

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.