Pythonic manera única para hacer el trabajo por primera vez una variable se llama
-
22-09-2019 - |
Pregunta
mi clase Python tiene algunas variables que requieren trabajo para calcular la primera vez que se llaman. Las llamadas posteriores sólo debe devolver el valor previamente calculado.
No quiero perder el tiempo haciendo este trabajo a menos que sean realmente necesarios por parte del usuario. Entonces, ¿hay una manera Pythonic limpia para poner en práctica este caso de uso?
Mi idea inicial era utilizar la propiedad () para llamar a una función del primer tiempo y luego anular la variable:
class myclass(object):
def get_age(self):
self.age = 21 # raise an AttributeError here
return self.age
age = property(get_age)
Gracias
Solución
class myclass(object):
def __init__(self):
self.__age=None
@property
def age(self):
if self.__age is None:
self.__age=21 #This can be a long computation
return self.__age
Alex mencionó que puede utilizar __getattr__
, así es como funciona
class myclass(object):
def __getattr__(self, attr):
if attr=="age":
self.age=21 #This can be a long computation
return super(myclass, self).__getattribute__(attr)
__getattr__()
se invoca cuando el atributo no existe en el objeto, es decir. la primera vez que intente acceder age
. Cada vez después, existe por lo age
__getattr__
no consigue llamado
Otros consejos
property
, como hemos visto, no deje que lo sustituya. Es necesario utilizar un enfoque ligeramente diferente, como por ejemplo:
class myclass(object):
@property
def age(self):
if not hasattr(self, '_age'):
self._age = self._big_long_computation()
return self._age
Hay otros enfoques, tales como __getattr__
o una clase de descriptor de costumbre, pero éste es más simple -)
Aquí es decorador de Python Cookbook para este problema:
class CachedAttribute(object):
''' Computes attribute value and caches it in the instance. '''
def __init__(self, method, name=None):
# record the unbound-method and the name
self.method = method
self.name = name or method.__name__
def __get__(self, inst, cls):
if inst is None:
# instance attribute accessed on class, return self
return self
# compute, cache and return the instance's attribute value
result = self.method(inst)
setattr(inst, self.name, result)
return result
Si usted puede utilizar las propiedades, aunque la evaluación perezosa también a menudo se lleva a cabo usando descriptores, véase, por ejemplo: