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'')