How decorators work with classes in python

I tried to understand how a particular single element decorator implementation for a class works, but I just got confused.

Here is the code:

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 is the syntax sugar for cls = deco(cls) , so in this code, when we define our cls class and wrap it with this singleton decorator, cls will no longer be a class, but a function. Python dynamically searches for which objects the variables belong to, so later we try to create an instance of our class, and this line of code works instance = cls(*args, **kwargs) , will we move on to infinite recursion? cls not a class at the moment, it is a function, so it should call itself by going into recursion.

But it works great. A singleton is created, and recursion does not occur. How it works?

+7
python decorator singleton
source share
3 answers

The inner function closes with the local variable cls .

cls is a reference to a class. He never bounces on anything else.

The decorator returns a function that returns an instance, but this does not affect the fact that the cls internal variable refers to

+4
source share

cls is a reference to the source class passed to the decorator. He retains the value that he had when the decorator was called. Its value is "captured" in the function returned by the decorator; for unclear reasons, this is called closure. Most languages ​​in which functions are first-class objects have this capability.

+3
source share
 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 

You'll get:

 <class '__main__.TryMe'> <__main__.TryMe object at 0x10231c9d0> 
+2
source share

All Articles