Search code examples
pythonpython-3.xdecoratorpython-decorators

Why don't we call the function instead of returning it when writing a decorator?


I am learning decorators in Python and came across a problem. I don't quite understand why instead of providing arguments in the decorator and returning the function with the arguments(as in @notaProperDecorator) we just return the object of the functions inside (@aProperDecorator).

def aProperDecorator(arg):
   print(arg)
   def outer(func):
      print("in outer")
      def inner(*args,**kwargs):
         print("in inner")
         return func(*args,**kwargs)
      return inner
   return outer

def functionToDecorate(*args,**kwargs):
   print("function")

def notaProperDecorator(arg):
   print(arg)
   def outer(func):
      print("in outer")
      def inner(*args,**kwargs):
         print("in inner")
         return func(*args,**kwargs)
      return inner(*args,**kwargs) #here
   return outer(func) #and here also

In this case, I thought something similar to Java would happen. That is, if a function returns a fuction we should directly call it (for example, return function("test"))
EDIT: As mentioned below, in my case the function outer is a proper decorator. I just wanted to use the complex case where both the decorator and the function can accept arguments.


Solution

  • When you write something like this:

    @decorator(arg)
    def defined_function():
        do_something()
    

    Python first calls decorator(arg). The function decorator should return another function (outer in your case). (Note that functions and classes are objects in Python, so it is possible to return them from functions. Also note that decorator is not a decorator, the actual decorator is outer.) Python calls the returned decorator with defined_function as an argument. The decorator should then do something with defined_function and return a new function - or something else, as @MadPhysicist said (inner in your case). Python will then replace defined_function with the new function.