Reputation: 915
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)
Upvotes: 14
Views: 12159
Reputation: 8437
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.
Upvotes: 16
Reputation: 23213
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)
Upvotes: 5