ProgramlamaPython Geliştirici, Veri Bilimci

Python'da memoizasyon nedir, ne amaçla kullanılır, elle ve dilin standart araçlarıyla nasıl uygulanır?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

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:

  • Özyinelemeli veya hesaplama açısından yoğun fonksiyonları, mantığını değiştirmeden hızlandırmaya olanak tanır
  • Uygulama elle (sözlükle) ve otomatik (lru_cache ile) olabilir
  • Değiştirilebilir argümanlarla dikkatli olunmalıdır, çünkü lru_cache yalnızca hashlenebilir (değişmez) argümanlarla çalışır

Tuzak Sorular.

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.

Tipik Hatalar ve Antipatternler

  • Önbellek sınırlaması olmadan memoization kullanmak ve belleği aşırı yüklemek
  • Değiştirilebilir argümanlara sahip fonksiyonları memoize etmeye çalışmak
  • Artık gerekmediğinde önbelleğin temizlenmesini unutmamak

Gerçek Hayattan Bir Örnek

Olumsuz Durum

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:

  • Tekrar eden çağrılar için hızlı çalışır

Dezavantajlar:

  • Sınırsız bellek büyümesi
  • Bellek yetersizliği olasılığı

Olumlu Durum

maxsize ile lru_cache kullanmak:

from functools import lru_cache @lru_cache(maxsize=1000) def foo(x): return long_heavy_computation(x)

Avantajlar:

  • Sınırlı önbellek boyutu
  • Eski değerlerin otomatik olarak kaldırılması

Dezavantajlar:

  • Değiştirilebilir argümanlarla ilgili sınırlamaları anlamak gerekir