una - paso por valor y referencia python
¿Cómo pasar un valor de argumento predeterminado de un miembro de instancia a un método? (3)
Quiero pasar un argumento predeterminado a un método de instancia usando el valor de un atributo de la instancia:
class C:
def __init__(self, format):
self.format = format
def process(self, formatting=self.format):
print(formatting)
Al intentar eso, aparece el siguiente mensaje de error:
NameError: name ''self'' is not defined
Quiero que el método se comporte así:
C("abc").process() # prints "abc"
C("abc").process("xyz") # prints "xyz"
¿Cuál es el problema aquí, por qué esto no funciona? ¿Y cómo podría hacer que esto funcione?
"self" necesita pasar como el primer argumento para cualquier clase de funciones si desea que se comporten como métodos no estáticos.
se refiere al objeto en sí. No se puede pasar "self" como argumento predeterminado ya que su posición se corrige como primer argumento.
En su caso, en lugar de "formatear = self.format", use "formatting = None" y luego asigne el valor del código de la siguiente manera:
[EDITAR]
class c:
def __init__(self, cformat):
self.cformat = cformat
def process(self, formatting=None):
print "Formating---",formatting
if formatting == None:
formatting = self.cformat
print formatting
return formatting
else:
print formatting
return formatting
c("abc").process() # prints "abc"
c("abc").process("xyz") # prints "xyz"
Nota: no use "formato" como nombre de variable, porque es función incorporada en python
En Python, el nombre self
no es especial. Es solo una convención para el nombre del parámetro, por lo que hay un parámetro self
en __init__
. (De hecho, __init__
tampoco es muy especial y, en particular, no crea realmente el objeto ... esa es una historia más larga)
C("abc").process()
crea una instancia de C
, busca el método de process
en la clase C
y llama a ese método con la instancia de C
como el primer parámetro. Así que terminará en el parámetro self
si lo proporcionó.
Sin embargo, incluso si tuviera ese parámetro, no se le permitiría escribir algo como def process(self, formatting = self.formatting)
, porque self
aún no está dentro del alcance en el punto en el que establece el valor predeterminado. En Python, el valor predeterminado para un parámetro se calcula cuando la función se compila y se "pega" a la función. (Esta es la misma razón por la que, si utiliza un valor predeterminado como []
, esa lista recordará los cambios entre las llamadas a la función).
¿Cómo podría hacer este trabajo?
La forma tradicional es usar None
como predeterminado, y verificar ese valor y reemplazarlo dentro de la función. Puede encontrar que es un poco más seguro hacer un valor especial para el propósito (una instancia de object
es todo lo que necesita, siempre que lo oculte para que el código de llamada no use la misma instancia) en lugar de None
. De cualquier manera, debe verificar este valor con is
, not ==
.
Realmente no puede definir esto como el valor predeterminado, ya que el valor predeterminado se evalúa cuando se define el método que está antes de que exista alguna instancia. Una solución fácil es hacer algo como esto:
class C:
def __init__(self, format):
self.format = format
def process(self, formatting=None):
formatting = formatting if formatting is not None else self.format
print(formatting)
self.format
solo se utilizará si el formatting
es None
.
Para demostrar el punto de cómo funcionan los valores predeterminados, vea este ejemplo:
def mk_default():
print("mk_default has been called!")
def myfun(foo=mk_default()):
print("myfun has been called.")
print("about to test functions")
myfun("testing")
myfun("testing again")
Y la salida aquí:
mk_default has been called!
about to test functions
myfun has been called.
myfun has been called.
Observe cómo se mk_default
una sola vez, y eso sucedió antes de que se llamara alguna vez a la función.