Decorator vs Wrapper Functions

Hello!

I am curious why the ‘outside’ decorator function is necessary when it seems to be that the contained wrapper function is the one doing the heavy lifting.

For example:

def some_decorator():
   def some_wrapper():
       some_operation 
   return some_operation

@ some_decorator 
def decorated_function()
...

It is unclear to me why above we could not just define the wrapper function and then use this function as the decorator with the @ syntax.
Also, why are we not returning anything from within the some_wrapper function?

Thanks in advance!

The set-up there seems a little odd and might be adding to the confusion. It would normally look more like the following-

def some_decorator():
   def some_wrapper():
       some_operation
       return some_operation
   return some_wrapper

@ some_decorator 
def decorated_function()

The real difference is in what you return after decorating your function. With the wrapper function you return an entirely new function!

Okay, that is why the tutorial would have explained this by stating we are adding additional ‘functionality’ - because you literally are!

But could we not also just use the following and get the same result :

def some_wrapper():
       some_operation
return some_operation

@ some_wrapper 
def decorated_function()

The syntax @some_wrapper acts like-
decorated_function = some_wrapper(decorated_function)

Ok fine, all good so far but follow this one further step. The problem here is that your return from that statement to be of limited use. decorated_function itself should be callable, it should take arguments.

If some_wrapper(decorated_function) returned something that is not itself callable then you’ve just mullered your function (it would also likely break existing usage of that function).

Long story short, by returning a function your function still acts like a… function.

Interesting. How might this break your function!?