Notes on Python Decorator
Python decorator is a function wrapper. It helps you wrap essential tasks around your functions such as logging, ratelimits, metrics updates etc. However, it has a peculiar behavior due to its dynamic implementation.
If you run the following code, what is the expected output?
def register(func):
print("hello to decorator!")
def another():
┆ print("wrapped now!")
┆ func()
return another
@register
def test():
print("I am a test function")
return ""
The interesting thing about this code is that it prints the line “hello to decorator” even without any function invocation.
But Why?
The reason is that during the decorator application to the function test interpreter would run all the code inside decorator and prepare a new function object. Decorator essentially creates new functions. Since the new function is created dynamically, Python VM runs all the code inside the wrapper (decorator) function and ultimately retunrs a new function object.
Another example
import sys
def first(func):
print("hello sir!")
return func
def second(func):
print(sys.argv[0])
for i in range(1,5):
┆ print(i)
def another():
┆ print("hello sir!")
┆ func()
return another
@first
def test():
print("I am a test function1")
return ""
# Should cause conflict, but doesn't
@first
def test():
print("I am a test function1")
return ""
# Another function with the same name
# Python VM does not complain of name conflict as
# the decorated function would assume a new name
@second
def test():
print("I am a test function2")
return ""
Output
$ python mydecor.py
hello sir!
hello sir!
mydecor.py
1
2
3
4
Things to look for
- There is no name collison problem for a decorated function
- A decorated function get a name of parent function and and offset
- Decorator code is run even before
main()
is called
References
Sample code
def register(func): | |
print("hello sir!") | |
def another(): | |
┆ print("hello sir!") | |
┆ func() | |
return another | |
@register1 | |
def test(): | |
print("I am a test function") | |
return "" |
Written with StackEdit.