Rozważ następujące:
@property
def name(self):
if not hasattr(self, '_name'):
# expensive calculation
self._name = 1 + 1
return self._name
Jestem nowy, ale myślę, że buforowanie można rozłożyć na dekorator. Tylko że takiego nie znalazłem;)
PS rzeczywiste obliczenia nie zależą od zmiennych wartości
python
caching
decorator
memoization
Tobias
źródło
źródło
Odpowiedzi:
Począwszy od Pythona 3.2 jest wbudowany dekorator:
@functools.lru_cache(maxsize=100, typed=False)
Przykład pamięci podręcznej LRU do obliczania liczb Fibonacciego :
Jeśli utkniesz z Pythonem 2.x, oto lista innych kompatybilnych bibliotek zapamiętywania:
functools32
| PyPI | Kod źródłowyrepoze.lru
| PyPI | Kod źródłowypylru
| PyPI | Kod źródłowybackports.functools_lru_cache
| PyPI | Kod źródłowyźródło
lru_cache
wykonania kopii dowolnego wyniku, który jest zapisywany w pamięci podręcznej, a taka kopia nie jest tworzona wfunctools.lru_cache
implementacji. Takie postępowanie groziłoby również stworzeniem trudnych do znalezienia problemów z pamięcią, gdy jest używane do buforowania dużego obiektu.Wygląda na to, że nie prosisz o dekorator zapamiętywania ogólnego przeznaczenia (tj. Nie interesuje Cię ogólny przypadek, w którym chcesz buforować wartości zwracane dla różnych wartości argumentów). Oznacza to, że chciałbyś mieć to:
podczas gdy dekorator zapamiętywania ogólnego przeznaczenia dałby ci to:
Twierdzę, że składnia wywołania metody jest lepsza, ponieważ sugeruje możliwość kosztownych obliczeń, podczas gdy składnia właściwości sugeruje szybkie sprawdzenie.
[Aktualizacja: Oparty na klasach dekorator zapamiętywania, z którym łączyłem się i cytowałem tutaj wcześniej, nie działa dla metod. Zastąpiłem go funkcją dekoratora.] Jeśli chcesz użyć dekoratora do zapamiętywania ogólnego przeznaczenia, oto prosty:
Przykładowe użycie:
Kolejny dekorator zapamiętywania z ograniczeniem rozmiaru pamięci podręcznej można znaleźć tutaj .
źródło
fibonacci
. Ta funkcja zawsze używa tego samegomemo
słownika.Przykładowe zastosowania:
źródło
functools.cached_property
Dekorator Pythona 3.8https://docs.python.org/dev/library/functools.html#functools.cached_property
cached_property
z Werkzeug wspomniano na: https://stackoverflow.com/a/5295190/895245, ale podobno pochodna wersja zostanie scalona z wersją 3.8, co jest niesamowite.Ten dekorator może być postrzegany jako buforowanie
@property
lub jako środek czyszczący,@functools.lru_cache
gdy nie masz żadnych argumentów.Doktorzy mówią:
źródło
Werkzeug ma
cached_property
dekoratora ( dokumentacja , źródło )źródło
Zakodowałem tę prostą klasę dekoratora, aby buforowała odpowiedzi funkcji. Uważam, że jest to BARDZO przydatne w moich projektach:
Użycie jest proste:
źródło
@cached
brakuje nawiasu. W przeciwnym razie zwrócicached
obiekt tylko w miejscemyfunc
i po wywołaniu, tak jakmyfunc()
wtedyinner
, zawsze zostanie zwrócony jako wartość zwracanaZRZECZENIE SIĘ: Jestem autorem kids.cache .
Powinieneś sprawdzić
kids.cache
, zawiera@cache
dekorator, który działa na Pythonie 2 i Pythonie 3. Brak zależności, ~ 100 linii kodu. Jest to bardzo proste w użyciu, na przykład, mając na uwadze swój kod, możesz go użyć w następujący sposób:Następnie
Lub możesz umieścić
@cache
dekorator po@property
(ten sam wynik).Używanie pamięci podręcznej do właściwości nazywa się leniwym szacowaniem ,
kids.cache
może zrobić znacznie więcej (działa na funkcji z dowolnymi argumentami, właściwościami, dowolnym typem metod, a nawet klasami ...). Dla zaawansowanych użytkownikówkids.cache
obsługuje,cachetools
które zapewnia fantazyjne magazyny pamięci podręcznej dla python 2 i python 3 (LRU, LFU, TTL, RR cache).WAŻNA UWAGA : domyślnym magazynem pamięci podręcznej
kids.cache
jest standardowy dykt, który nie jest zalecany dla długo działających programów z ciągle różnymi zapytaniami, ponieważ prowadziłoby to do stale rosnącego magazynu buforowania. W tym celu możesz podłączyć inne sklepy z pamięcią podręczną, używając na przykład (@cache(use=cachetools.LRUCache(maxsize=2))
do dekoracji funkcji / właściwości / klasy / metody ...)źródło
c
oMyClass
i sprawdzić jeobjgraph.show_backrefs([c], max_depth=10)
, to łańcuch ref z klasą obiektuMyClass
doc
. To znaczy,c
nigdy nie zostałby zwolniony, dopóki nieMyClass
został zwolniony.Ach, po prostu potrzebowałem znaleźć odpowiednią nazwę: „ Leniwa ocena nieruchomości ”.
Ja też to często robię; może kiedyś użyję tego przepisu w moim kodzie.
źródło
Jest fastcache , czyli „implementacja Pythona 3 functools.lru_cache w C. Zapewnia 10-30-krotne przyspieszenie w stosunku do standardowej biblioteki”.
Taka sama jak wybrana odpowiedź , tylko inny import:
Jest również instalowany w Anaconda , w przeciwieństwie do functools, które należy zainstalować .
źródło
functools
jest częścią standardowej biblioteki, zamieszczony link prowadzi do losowego widelca git lub czegoś innego ...Istnieje jeszcze jeden przykład dekoratora memoize na Python Wiki:
http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize
Ten przykład jest nieco sprytny, ponieważ nie buforuje wyników, jeśli parametry są zmienne. (sprawdź ten kod, to bardzo proste i interesujące!)
źródło
Jeśli używasz Django Framework, ma on taką właściwość, aby buforować widok lub odpowiedź interfejsu API,
@cache_page(time)
a także mogą istnieć inne opcje.Przykład:
Więcej szczegółów można znaleźć tutaj .
źródło
Wraz z przykładem Memoize znalazłem następujące pakiety Pythona:
źródło
Zaimplementowałem coś takiego, używając pickle dla wytrwałości i używając sha1 dla krótkich, prawie na pewno unikalnych identyfikatorów. Zasadniczo pamięć podręczna haszowała kod funkcji i hist argumentów, aby uzyskać sha1, a następnie szukał pliku z tym sha1 w nazwie. Jeśli istniał, otwierał go i zwracał wynik; jeśli nie, wywołuje funkcję i zapisuje wynik (opcjonalnie zapisuje tylko wtedy, gdy przetworzenie zajęło pewien czas).
To powiedziawszy, przysięgam, że znalazłem istniejący moduł, który to zrobił i znalazłem się tutaj, próbując znaleźć ten moduł ... Najbliższy, jaki mogę znaleźć, to ten, który wygląda dobrze: http: //chase-seibert.github. io / blog / 2011/11/23 / pythondjango-disk-based-caching-decorator.html
Jedynym problemem, jaki widzę z tym, jest to, że nie działałoby to dobrze w przypadku dużych danych wejściowych, ponieważ haszuje str (arg), co nie jest unikalne dla gigantycznych tablic.
Byłoby miło, gdyby istniał protokół unique_hash (), który miałby klasę zwracającą bezpieczny hash swojej zawartości. W zasadzie ręcznie zaimplementowałem to dla typów, na których mi zależało.
źródło
Wypróbuj joblib http://pythonhosted.org/joblib/memory.html
źródło
Jeśli używasz Django i chcesz buforować widoki, zobacz odpowiedź Nikhila Kumara .
Ale jeśli chcesz buforować DOWOLNE wyniki funkcji, możesz użyć django-cache-utils .
Ponownie wykorzystuje pamięci podręczne Django i zapewnia łatwy w użyciu
cached
dekorator:źródło
@lru_cache
nie jest doskonały z domyślnymi wartościami funkcjimój
mem
dekorator:i kod do testowania:
wynik - tylko 3 razy ze snem
ale z
@lru_cache
nim będzie 4 razy, bo to:zostanie obliczony dwukrotnie (źle działa z domyślnymi)
źródło