Why and how __call__ is called in python decorators

class myDecorator(object): def __init__(self, f): print "inside myDecorator.__init__()" f() # Prove that function definition has completed def __call__(self): print "inside myDecorator.__call__()" @myDecorator def aFunction(): print "inside aFunction()" def main(): print "main starts....." aFunction() print "main ends....." 

Output:

 inside myDecorator.__init__() inside aFunction() main starts..... inside myDecorator.__call__() main ends..... 

I could not understand the following points regarding the code above:

  • Why is "main starts ..." not the first line to print?

  • Suppose that if I return some value from aFunction (), it will not be available instead of calling it, because aFunction() is replaced by inside myDecorator.__call__() not inside aFunction() .

+4
source share
2 answers

Decorator Syntax:

 @myDecorator def aFunction(): … 

equivalent to this:

 def aFunction(): … aFunction = myDecorator(aFunction) 

If myDecorator is a class, then you expect __init__ be called when the function is defined. Instead, an instance of the class is used. When you call it, you expect __call__ be called, so where the f() call should go.

+6
source

Function definition in Python

 def foo(): pass 

actually convenient for the programmer to say something like (pseudocode) *:

 foo = function(code=compile('pass', ...), globals=globals(), name='foo') 

therefore, the shell is simply in between:

 foo = my_wrapper(function(...)) 

if the wrapper is a class, __init__ is called. if it is a function, it will be called. After this statement, everything works as usual.


* This pseudo code is not so far from the real code:

 >>> def bar(): pass ... >>> body = compile('print("hello")', '', 'exec') >>> function = type(bar) >>> foo = function(body, globals(), 'foo') >>> foo() hello 
+2
source

Source: https://habr.com/ru/post/1484211/


All Articles