Domanda

la mia classe Python ha alcune variabili che richiedono un lavoro per calcolare la prima volta che vengono chiamati. Le chiamate successive dovrebbero solo restituire il valore precalcolate.

Non voglio sprecare tempo a fare questo lavoro a meno che non siano effettivamente necessarie per l'utente. Quindi c'è un modo Pythonic pulito per implementare questo caso d'uso?

Il mio primo pensiero è stato quello di utilizzare la proprietà () per chiamare una funzione per la prima volta e poi ignorare la variabile:

class myclass(object):
    def get_age(self):
        self.age = 21 # raise an AttributeError here
        return self.age

    age = property(get_age)

Grazie

È stato utile?

Soluzione

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 menzionato è possibile utilizzare __getattr__, questo è come funziona

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__() viene richiamato quando l'attributo non esiste sull'oggetto, cioè. la prima volta che si tenta di accedere age. Ogni volta dopo, age esiste quindi __getattr__ non viene chiamato

Altri suggerimenti

property, come avete visto, non permette di ignorare esso. È necessario utilizzare un approccio leggermente diverso, come ad esempio:

class myclass(object):

    @property
    def age(self):
      if not hasattr(self, '_age'):
        self._age = self._big_long_computation()
      return self._age

Ci sono altri approcci, come __getattr__ o di una classe descrittore personalizzato, ma questo è più semplice -!)

Qui è decoratore da Python Cookbook per questo 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

Sì, è possibile utilizzare le proprietà, anche se la valutazione pigra viene spesso realizzato utilizzando descrittori, vedi per esempio:

http://blog.pythonisito.com/2008/08/lazy -descriptors.html

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top