Dict mit zeitlich begrenzten Schlüsseln

Code-Stücke können hier veröffentlicht werden.
Antworten
Sorgenkind
User
Beiträge: 34
Registriert: Samstag 24. Juli 2004, 19:25
Kontaktdaten:

Dienstag 30. November 2004, 21:54

Hallo

Ich hab ein Dictionary geschrieben bei dem die Schlüssel nach einer bestimmten Zeit verfallen...

Eigentlich nichts besonderes.

Aber es gibt eine besonderheit im zusammenhang mit python 2.4.
Die ganze class kann als decorator verwendet werden und so als Cache für eine Funktion dienen.

Code: Alles auswählen

import time

class Cache(dict):
    __slots__=["timeout","cache"]
    def __init__(self,timeout=0):
        self.timeout=timeout
        self.cache={}

    def __setitem__(self,x,y):
        super(Cache,self).__setitem__(x,y)
        self.cache[x]=time.time()

    def __contains__(self,x):
        if x in self.cache:
            if self.timeout and time.time()-self.cache[x]>self.timeout:
                del self[x],self.cache[x]
                return False
            return True
        return False

    def __getitem__(self,x):
        if x in self:
            return super(Cache,self).__getitem__(x)
        raise KeyError(x)

    def get(self,x,std=None):
        if x in self:
            return self[x]
        return std

    def add(self,x,y,t=None):
        """"Fügt etwas mit einem anderen Timeout hinzu..."""
        t=time.time()-(t or 0)
        super(Cache,self).__setitem__(x,y)
        self.cache[x]=t

    def cleanup(self):
        map(self.__contains__,self)

    def clear(self):
        super(Cache,self).clear()
        self.cache.clear()

    def __call__(self,func):
        def x(a,reset=False,*b,**c):
            if a in self and not reset:
                return self[a]
            y=func(a,*b,**c)
            self[a]=y
            return y
        return x
Einfachen Beispiel:

Code: Alles auswählen

>>> @Cache(10)
... def t(x):
... 	print "In Cache geladen!"
... 	return x**2
... 
>>> t
<function x at 0x0118E2B0>
>>> t(4)
In Cache geladen!
16
>>> t(4)
16
>>> t(4) #10 sek später
In Cache geladen!
16
>>> @Cache(0) #keys verfallen nie
... def t(x):
... 	print "In Cache geladen!"
... 	return x**2
... 
>>> t(10)
In Cache geladen!
100
>>> t(10)
100
>>> t(10) #bisschen später
100
>>> t(10) #viel später ;)
100
>>> t(10,reset=True) #reset
In Cache geladen!
100
bei x**2 isses jetzt nicht der irre performance boost soll ja nur als beispiel dienen...

Ich verwende es selber zum Abfragen größtenteils statischer datenbankdaten damit nicht immer die gleichen daten aus der mysql datenbank abgefragt werden
Antworten