2016-02-10 14 views
7

Próbowałem zrozumieć, jak działa pewna implementacja dekoratora singleton dla klasy, ale tylko się zdezorientowałem.Jak działają dekoratory z klasami w pythonach

Oto kod:

def singleton(cls): 
    instance = None 

    @functools.wraps(cls) 
    def inner(*args, **kwargs): 
     nonlocal instance 
     if instance is None: 
      instance = cls(*args, **kwargs) 
     return instance 
    return inner 

@deco jest cukrem syntatic dla cls = deco(cls), więc w tym kodzie, gdy definiujemy naszą cls klasę i owinąć go z tego singleton dekoratora, cls nie będzie klasa anymore , ale funkcja. Python dynamicznie wyszukuje, do jakich obiektów są przypisane zmienne, więc później staramy się utworzyć instancję naszej klasy, a ta linia kodu działa instance = cls(*args, **kwargs), czy nie przejdziemy do nieskończonej rekursji? cls nie jest w tej chwili klasą, jest funkcją, więc powinien się wywoływać, wchodząc w rekursję.

Ale działa dobrze. Tworzy się singletone i nie ma rekurencji. Jak to działa?

Odpowiedz

4

Funkcja inner jest zamykana przez lokalną zmienną cls.

cls to odniesienie do klasy. To nigdy nie jest odbijane do niczego innego.

Dekorator zwraca funkcję, która zwraca instancję, ale nie wpływa to na co wewnętrzna zmienna cls dotyczy

3

cls to odniesienie do oryginalnej klasy przekazanej dekoratorowi. Zachowuje wartość, jaką miał przy wywołaniu dekoratora. Jego wartość jest "uwięziona" w funkcji zwróconej przez dekorator; z niewiadomych powodów nazywa się to zamknięciem . Większość języków, w których funkcje są obiektami pierwszej klasy, ma taką możliwość.

2
def singleton(cls): 
    instance = None 

    @functools.wraps(cls) 
    def inner(*args, **kwargs): 
     nonlocal instance 
     if instance is None: 
      instance = cls(*args, **kwargs) 
      print cls 
     return instance 
    return inner 

@singleton 
class TryMe(object): 
    pass 

m = TryMe() 
print m 

Dostaniesz:

<class '__main__.TryMe'> 
<__main__.TryMe object at 0x10231c9d0> 
Powiązane problemy