Frage

meine Python-Klasse hat einige Variablen, die Arbeit benötigen sie zum ersten Mal aufgerufen wird, zu berechnen. Nachfolgende Aufrufe sollten nur den vorberechneten Wert zurück.

Ich mag nicht, Zeit zu tun, diese Arbeit verschwenden, wenn sie tatsächlich vom Benutzer benötigt werden. So ist es eine saubere Art und Weise Pythonic diesen Anwendungsfall zu implementieren?

Mein erster Gedanke war Eigentum () zu verwenden, das erste Mal eine Funktion aufrufen und dann die Variable außer Kraft setzen:

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

    age = property(get_age)

Danke

War es hilfreich?

Lösung

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 erwähnt Sie __getattr__ verwenden können, das ist, wie es funktioniert

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__() aufgerufen wird, wenn das Attribut nicht auf das Objekt existiert, das heißt. das erste Mal, wenn Sie versuchen, den Zugang age. Jedes Mal, nachdem existiert age so __getattr__ nicht genannt bekommt

Andere Tipps

property, wie Sie gesehen haben, werden Sie es nicht zulassen, außer Kraft setzen. Sie benötigen einen etwas anderen Ansatz, wie zu verwenden:

class myclass(object):

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

Es gibt auch andere Ansätze, wie __getattr__ oder eine benutzerdefinierten Descriptor-Klasse, aber dies ist einfacher! -)

Hier Dekorateur von Python-Kochbuch für dieses Problem:

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

Ja, Sie Eigenschaften verwenden können, obwohl lazy evaluation auch oft Deskriptoren durchgeführt wird, siehe z:

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top