una - Valores por defecto para los parámetros de función en Python
pasar una lista como parametro en python (4)
El valor predeterminado para los parámetros se evalúa en "compilación", una vez. Entonces, obviamente, no puedes acceder a ti self
. El ejemplo clásico es la list
como parámetro predeterminado. Si agrega elementos en él, ¡el valor predeterminado para el parámetro cambia!
La solución consiste en utilizar otro parámetro predeterminado, generalmente None
, y luego verificar y actualizar la variable.
Posible duplicado:
valor predeterminado del parámetro como resultado del método de instancia
Si bien es posible establecer valores predeterminados para los parámetros de función en python:
def my_function(param_one=''default'')
...
Parece que no es posible acceder a la instancia actual (self):
class MyClass(..):
def my_function(self, param_one=self.one_of_the_vars):
...
Mis preguntas):
- ¿Es esto cierto que no puedo acceder a la instancia actual para establecer el parámetro predeterminado en las funciones?
- Si no es posible: ¿cuáles son las razones y es imaginable que esto sea posible en futuras versiones de python?
Está escrito como:
def my_function(self, param_one=None): # Or custom sentinel if None is vaild
if param_one is None:
param_one = self.one_of_the_vars
Y creo que es seguro decir que nunca sucederá en Python debido a la naturaleza de que el self
realmente no existe hasta que la función comience ... (no se puede hacer referencia a ella, en su propia definición, como todo lo demás)
Por ejemplo: no se puede hacer d = {''x'': 3, ''y'': d[''x''] * 5}
Hay mucho más de lo que piensas. Considere que los valores predeterminados son estáticos (= referencia constante apuntando a un objeto) y almacenados en algún lugar de la definición; evaluado en el tiempo de definición del método; como parte de la clase , no como la instancia. Como son constantes, no pueden depender de self
.
Aquí hay un ejemplo. Es contrario a la intuición, pero en realidad tiene perfecto sentido:
def add(item, s=[]):
s.append(item)
print len(s)
add(1) # 1
add(1) # 2
add(1, []) # 1
add(1, []) # 1
add(1) # 3
Esto imprimirá 1 2 1 1 3
.
Porque funciona de la misma manera que
default_s=[]
def add(item, s=default_s):
s.append(item)
Obviamente, si modifica default_s
, conserva estas modificaciones.
Hay varias soluciones, incluidas
def add(item, s=None):
if not s: s = []
s.append(item)
o podrías hacer esto:
def add(self, item, s=None):
if not s: s = self.makeDefaultS()
s.append(item)
Entonces el método makeDefaultS
tendrá acceso a self
.
Otra variación:
import types
def add(item, s=lambda self:[]):
if isinstance(s, types.FunctionType): s = s("example")
s.append(item)
aquí el valor predeterminado de s
es una función de fábrica .
Puedes combinar todas estas técnicas:
class Foo:
import types
def add(self, item, s=Foo.defaultFactory):
if isinstance(s, types.FunctionType): s = s(self)
s.append(item)
def defaultFactory(self):
""" Can be overridden in a subclass, too!"""
return []
Hay varias suposiciones falsas que hace aquí: Primero, la función pertenece a una clase y no a una instancia, lo que significa que la función real involucrada es la misma para dos instancias de una clase. En segundo lugar, los parámetros predeterminados se evalúan en tiempo de compilación y son constantes (como en, una referencia de objeto constante; si el parámetro es un objeto mutable, puede cambiarlo). Por lo tanto, no puede acceder a self
en un parámetro predeterminado y nunca podrá hacerlo.