Sorunun Tarihi:
Memoizasyon, aynı argümanlarla tekrar tekrar çağrılan fonksiyonların olduğu durumlarda, işlevsel programlama, özyinelemeli hesaplamalar ve dinamik programlama alanında yaygın olarak kullanılan bir optimizasyon tekniğidir. Python'da, functools.lru_cache dekoratörünün ve hesaplama sonuçlarının önbelleklenmesi kalıplarının varlığıyla kullanılmaya başlandı.
Sorun:
Önbellekleme olmadan, Fibonacci sayıları gibi özyinelemeli fonksiyonlar çok yavaş çalışır: her argüman için hesaplamalar tekrar tekrar yapılır ve bu da çağrı sayısının üssel olarak artmasına yol açar.
Çözüm:
Memoizasyon, daha önce hesaplanmış değerleri (örneğin, bir sözlükte) saklayarak ihtiyaç duyulduğunda yeniden kullanılmasını sağlar:
Elle uygulama örneği:
memo = {} def fib(n): if n in memo: return memo[n] if n <= 1: result = n else: result = fib(n-1) + fib(n-2) memo[n] = result return result
Python 3.2'den itibaren sadece dekoratör kullanabilirsiniz:
from functools import lru_cache @lru_cache(maxsize=128) def fib(n): if n <= 1: return n return fib(n-1) + fib(n-2)
Ana Özellikler:
Değiştirilebilir argümanlara sahip bir fonksiyonu memoize etmek mümkün mü (örneğin, listeler)?
Hayır, lru_cache tüm argümanların hashlenebilir olmasını gerektirir (değişmez), aksi takdirde TypeError oluşur.
from functools import lru_cache @lru_cache # def f(a): return a[0] # TypeError: unhashable type: 'list'
Memoize edilmiş değerler otomatik olarak silinir mi?
Evet, maxsize ayarlandığında — limitin dışına çıkan değerler silinir (En Az Kullanılan). Sonsuz bir önbellek (maxsize=None) bellek taşmasına yol açabilir.
Eğer memoize edilmiş bir fonksiyon kendisini yeni argümanlarla çağırırsa ne olur?
Memoizasyon yine de çalışır — her benzersiz argüman seti için sonuç yalnızca bir kez hesaplanır ve önbelleğe alınır.
Kendi sınırsız önbelleğini yazmak:
cache = {} def foo(x): if x not in cache: cache[x] = long_heavy_computation(x) return cache[x]
Bir süre sonra program gigabaytlarca bellek kullanıyor.
Avantajlar:
Dezavantajlar:
maxsize ile lru_cache kullanmak:
from functools import lru_cache @lru_cache(maxsize=1000) def foo(x): return long_heavy_computation(x)
Avantajlar:
Dezavantajlar: