una resueltos que metodos llamar instanciar instancia herencia ejercicios ejemplos como clases clase atributos atributo python

resueltos - metodos de clase python



¿Puedo usar un atributo de clase como valor predeterminado para un método de instancia? (2)

Eso es porque, según la documentation :

Los valores predeterminados de los parámetros se evalúan cuando se ejecuta la definición de la función. Esto significa que la expresión se evalúa una vez, cuando se define la función

Cuando se __init__() , la definición de MyClass está incompleta, ya que aún se está analizando, por lo que aún no puede referirse a MyClass.__DefaultName . Una forma de __init__() es pasar un valor único especial a __init__() , como None :

def __init__(self, name=None): if name is None: name = MyClass.__DefaultName # ...

Me gustaría usar un atributo de clase como valor predeterminado para uno de los argumentos del método __init__ mi clase. Sin embargo, esta construcción genera una excepción NameError y no entiendo por qué:

class MyClass(): __DefaultName = ''DefaultName'' def __init__(self, name = MyClass.__DefaultName): self.name = name

¿Por qué falla esto, y hay una manera de hacerlo que funcione?


Una cosa importante a tener en cuenta con Python es cuando se ejecutan diferentes bits de código, junto con el hecho de que class declaraciones de class y def se ejecutan cuando se ven , no solo se guardan para luego. Con una def es un poco más fácil de entender porque lo único que se está ejecutando es lo que está entre las () s, así que en su código anterior

def __init__( SELF, name = MyClass.__DefaultName ):

cuando Python ve MyClass.__DefaultName , trata de encontrarlo primero en el espacio de nombres local , luego en el espacio de nombres del módulo (también conocido como global ), y finalmente en los elementos builtins .

¿Cuál es el espacio de nombres local cuando se ejecuta una declaración de class ? Esa es la parte divertida: es lo que se convertirá en el espacio de nombres de class , pero en este momento es anónimo, por lo que no puede hacer referencia a él por su nombre (también conocido como MyClass en su código), pero puede hacer referencia directamente a cualquier cosa que ya haya sido definido ... y que se ha definido? En su ejemplo de clase solo una cosa - __DefaultName . Entonces tu __init__ debería verse así:

def __init__( SELF, name=__DefaultName ):

Tenga en cuenta que no puede cambiar MyClass._MyClass__DefaultName más adelante y que esos cambios se muestren en nuevas instancias. ¿Por qué? Debido a que __init__ def se ejecuta solo una vez, y el valor que __DefaultName tenía en ese momento se ha guardado y siempre se usará, a menos que especifique un nuevo valor directamente cuando cree una nueva instancia:

my_instance = MyClass(name=''new name'')