Herkes, _cachedf işlevi döndükten sonra bile önbellek değişkeninin hala nasıl olduğunu anlamanıza yardımcı olabilir mi?
Bu, Python'un referans sayma çöp toplayıcısına aittir. cache
değişkeni _cachedf
işlevinin bir referansı olduğundan ve cached
numaralı arayanın buna bir başvurusu olduğundan korunacak ve erişilebilir olacaktır. Fonksiyonu tekrar çağırdığınızda, orijinal olarak oluşturulmuş aynı işlev nesnesini kullanıyorsunuz, dolayısıyla önbelleğe erişebilirsiniz.
Tüm referanslar yok olana kadar önbelleği kaybetmezsiniz. Bunu yapmak için del
operatörünü kullanabilirsiniz.
Kayıt için
>>> import time
>>> def cached(f):
... cache = {} # <---- not an attribute this time!
... def _cachedf(*args):
... if args not in cache:
... cache[args] = f(*args)
... return cache[args]
... return _cachedf
...
...
>>> def foo(duration):
... time.sleep(duration)
... return True
...
...
>>> bob = cached(foo)
>>> bob(2) # Takes two seconds
True
>>> bob(2) # returns instantly
True
>>> del bob # Deletes reference to bob (aka _cachedf) which holds ref to cache
>>> bob = cached(foo)
>>> bob(2) # takes two seconds
True
>>>
, ne ulaşmaya çalıştığınız Memoization denir ve aynı şeyi yapar decorator pattern page edinilebilir daha eksiksiz memoizing dekoratör vardır, ancak kullanıyor: Örneğin
dekoratör sınıfı. Kodunuz ve sınıf tabanlı dekoratör, temelde aynıdır; sınıf tabanlı dekoratör, depolamadan önce karma yeteneğini kontrol eder.
Düzenleme (2017/02/02): @SiminJie cached(foo)(2)
daima bir gecikme katlandığı yorumlar.
Bunun nedeni, cached(foo)
'un yeni bir işlevi yeni bir önbellek ile döndürmesidir. cached(foo)(2)
çağrıldığında, yeni bir (boş) önbellek oluşturulur ve önbelleğe alınmış işlev hemen çağrılır.
Önbellek boş olduğundan ve değeri bulamadığı için, temel işlevi yeniden çalıştırır. Bunun yerine, cached_foo = cached(foo)
yapın ve daha sonra birden çok kez cached_foo(2)
numaralı telefonu arayın. Bu sadece ilk görüşme için gecikmeye neden olacaktır. Eğer dekoratörler aşina değilseniz
@cached
def my_long_function(arg1, arg2):
return long_operation(arg1,arg2)
my_long_function(1,2) # incurs delay
my_long_function(1,2) # doesn't
Yukarıdaki kod ne anlama geldiğini anlamak için this answer bakmak: Bir dekoratör olarak kullanılan eğer Ayrıca, beklendiği gibi çalışır.
Açıklama için çok teşekkürler, düzenlemeniz bazı şeyleri netleştirir. Merak ettim, (C) Python'un içsellerini öğrenmek için, son paragrafınızda bahsettiğiniz "hücre" ye, muayene ya da benzer bir şeyden söz etmek mümkün mü? – rahmu
@rahmu: Açıklamada bir hatayı düzelttim (çok fazla değişmez). Ne yazık ki, hücreler Python kodu için tamamen saydamdır ve her zaman başvurdukları nesne ile değiştirilir, böylece incelenemezler. –