-2

I am absolutly new in Python (I came from Java and C#)

I am stufying the decorator topic. So I have the following example:

# DECORATOR:
def my_decorator(func):
  def wrap_func():
    print('**************')
    func()
    print('**************')
  return wrap_func


@my_decorator
def hello():
  print('Hello World')

hello()

It seems to me that this is the logic (but I am not sure of this:

I am defining a my_decorator function taking another function as parameter. This my_decorator function wrap the function passed as parameter into a wrap_func() function that execute the function passed as parameter. In addition this wrap_func() function can perform some extra logic before and after the execution of the function passed as parameter (it is decorating the original function.

To say to the interpreter that a specific function have to use the decorator I have to use the syntax @decorator_name before the function definition.

So in my case: when I perform hello() call: Python know that the hello() function have to be decorated by my_decorator decorator so it is not directly executing the hello() function but it is performing the my_decorator() function passing hello() reference as parameter. So it can add extra logic before and after the hello() invoaction.

Is this reasoning correct or am I missing something??

I have another doubt: why the decorator function return the function that wrap our decoration logic?

AndreaNobili
  • 40,955
  • 107
  • 324
  • 596
  • 4
    Have you read anything on the subject before posting? I guess not… – Piotr Dobrogost Dec 15 '19 at 15:01
  • Does this answer your question? [How to make a chain of function decorators?](https://stackoverflow.com/questions/739654/how-to-make-a-chain-of-function-decorators) – Oliver W. Dec 15 '19 at 15:02

2 Answers2

3

A decorator is just syntactic sugar for a function call.

The decoration

@my_decorator
def hello():
    print('Hello world')

is equivalent to

def hello():
    print('Hello world')

hello = my_decorator(hello)

So in this case, using the decorator syntax is the same as defining the following function directly:

def hello():
    print('**************')
    print('Hello world')
    print('**************')

The decorator creates a function that calls print('**************'), then calls the original function, then calls print('**************') again.

If you had only planned on decorating once function, this is obviously just a lot of unnecessary boiler plate. But if you were decorating multiple functions, the abstraction pays off:

# DECORATOR:
def my_decorator(func):
  def wrap_func():
    print('**************')
    func()
    print('**************')
  return wrap_func


@my_decorator
def hello():
  print('Hello World')

@my_decorator
def how_are_you():
  print("How are you doing?")

@my_decorator
def goodbye():
  print('Goodbye, world')

vs

def hello():
    print('**************')
    print('Hello world')
    print('**************')

def how_are_your():
    print('**************')
    print('How are you doing')
    print('**************')

def good_bye():
    print('**************')
    print('Goodbye world')
    print('**************')

especially if you later decide to wrap each output with ============== instead of **************.

chepner
  • 497,756
  • 71
  • 530
  • 681
1

Decorators are just a syntactic sugar. This:

@decorator
def func():
    pass

is equivalent to this:

def func():
    pass

func = decorator(func)
RafalS
  • 5,834
  • 1
  • 20
  • 25