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.
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.
import sys def first(func): print("hello sir!") return func def second(func): print(sys.argv) 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 ""
$ 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
|┆ print("hello sir!")|
|print("I am a test function")|
Written with StackEdit.