2015-04-28 13 views
6

Aşağıdaki dekoratörünüz olduğunu varsayalım. Süslediği tüm işlevlere bazı liste referanslarını eklemek için nasıl değiştirilebilir?Bir dekoratörde nasıl kaydedileceği tüm işlevler nasıl kaydedilir?

def memoize(obj): 
    cache = obj.cache = {} 

    @functools.wraps(obj) 
    def memoizer(*args, **kwargs): 
     if args not in cache: 
      cache[args] = obj(*args, **kwargs) 
     return cache[args] 
    return memoizer 

@memoize 
def foo(bar): 
    return bar ** 3 
+0

"Bazı liste" nerede saklanır? Bunun global bir değişken olmasını mı yoksa bir şekilde dekoratörün kendisine mi bağlı kalmasını istersiniz? – BrenBarn

+3

bunu bir yöntem yerine bir sınıf haline getirin ... sonra her bir nesneyi '__init__' üzerine eklemek için bir statik değişken kullanın –

+0

@BrenBarn Hayır Gerçekten listenin nerede saklandığına dikkat etmiyorum. –

cevap

3

Kolayca dekoratör fonksiyonlu nesne üzerinde bir liste (memoize.decorated) saklayabilirsiniz:

_decorated = [] 

def memoize(obj): 
    cache = obj.cache = {} 

    # add to the decorated list 
    _decorated.append(obj) 

    @functools.wraps(obj) 
    def memoizer(*args, **kwargs): 
     if args not in cache: 
      cache[args] = obj(*args, **kwargs) 
     return cache[args] 
    return memoizer 

# make the list accessible from the decorator: 
memoize.decorated = _decorated 

Bu gibi kullanılabilir: Bir yan not olarak

@memoize 
def foo(bar): 
    return bar ** 3 

print memoize.decorated 

, şunları yapmalısınız bellek sızıntısını önlemek için WeakRefs in the list depolamayı veya bunlara başka "gerçek" referanslar kalmadığında boşaltılamayan nesneleri düşünün.

+2

değerini takdir ediyorum. cesaret kırıldı, çünkü bunlar sadece Python internals için olmalıydı. Burada bir "__" bile kullanmak için gerçek bir sebep yok. (Tek bir alt çizgi bile kullanmanın çok fazla sebebi yok, ama bu daha tartışmalı.) – BrenBarn

+0

@BrenBarn kabul ettim, isimlendirdim – shx2