2015-04-28 23 views
6

Załóżmy, że masz następujący dekorator. W jaki sposób można go zmodyfikować, dodając do niektórych odnośników do wszystkich funkcji, które zdobi?Jak zarejestrować w dekoratorze wszystkie funkcje, które zdobi?

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

Czy obchodzi Cię, gdzie "niektóre listy" są przechowywane? Czy chcesz, aby była to zmienna globalna lub jakoś powiązana z samym dekoratorem? – BrenBarn

+3

sprawiają, że klasa zamiast metody ... następnie użyj zmiennej statycznej do dołączenia każdego obiektu na '__init__' –

+0

@BrenBarn Nie naprawdę nie obchodzi mnie, gdzie lista jest przechowywana. –

Odpowiedz

3

można łatwo przechowywać listę na obiekcie dekorator-function (memoize.decorated):

_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 

To może być używany jak:

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

print memoize.decorated 

Na marginesie, należy rozważ przechowywanie WeakRefs in the list, aby uniknąć wycieku pamięci lub uwolnienia się obiektów, gdy nie pozostawia się żadnych "prawdziwych" odniesień do nich.

+2

Użycie '__' na początku i końcu nazwy jest zniechęcony, ponieważ te mają być tylko dla wewnętrznych Pythona. Nie ma prawdziwego powodu, aby używać nawet wiodącego '__' tutaj. (Powiedziałbym, że nie ma powodu, aby używać nawet jednego podkreślenia, ale jest to bardziej dyskusyjne.) – BrenBarn

+0

@BrenBarn zgodził się, poprawiłem nazewnictwo – shx2