14

I have below decorator demonstration code. If I execute it without explicitly calling greet function, it is executing print statement inside decorator function and outputs Inside decorator.

I am unable to understand this behavior of decorator. How the time_decorator is called even if I didn't call greet function?

I am using Python 3.

def time_decorator(original_func):
 print('Inside decorator')
 def wrapper(*args, **kwargs):
 start = time.clock()
 result = original_func(*args, **kwargs)
 end = time.clock()
 print('{0} is executed in {1}'.format(original_func.__name__, end-start))
 return result
 return wrapper
@time_decorator
def greet(name):
 return 'Hello {0}'.format(name)
asked Apr 5, 2016 at 19:21

2 Answers 2

16

Decorators are called at start time (when the python interpreter reads the code as the program starts), not at runtime (when the decorated function is actually called).

At runtime, it is the wrapped function wrapper which is called and which itself calls the decorated function and returns its result.

So this is totally normal that the print line gets executed.

If, i.e, you decorate 10 functions, you will see 10 times the print output. No need to even call the decorated functions for this to happen.

Move the print inside wrapper and this won't happen anymore.

Decorators as well as metaclasses are part of what is called meta-programming (modify / create code, from existing code). This is a really fascinating aspect of programming which takes time to understand but offers amazing possibilities.

answered Apr 5, 2016 at 19:23

2 Comments

Thank you @Apero! What is motivation behind calling decorator at compile time? Are there any objects that are called during compile time apart from decorators?
Yes, metaclasses also modify the classes they are "metaclassing" at compile time, not at runtime. Metaclasses and decorators can be seens like code hacks in a way, because they modify the code they respectively metaclass or decorate, without having to modify the initial code itself. Then whenever this "now code" gets called, the new hacked behaviour will happen.
5

time_decorator is executed during function decoration. wrapper is not (this is function invoked when decorated greet() is called).

@ is just syntactic sugar. Following code snippets are equivalent.

Decorator syntax:

@time_decorator
def greet(name):
 return 'Hello {0}'.format(name)

Explicit decoration process - decorator is a function that returns new function based on another one.

def greet(name):
 return 'Hello {0}'.format(name)
greet = time_decorator(greet)
answered Apr 5, 2016 at 19:25

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.