Just playing with decorators, and have a simple example I made. I was expecting that every time I called a method, the method name would be added to the list.
python_func_calls = []
def log_func_call(func):
python_func_calls.append(func.__name__)
return func
@log_func_call
def print_a():
print('I am the a function...')
@log_func_call
def print_b():
print('I am the b function...')
print_a()
print_b()
print_b()
print_a()
print(python_func_calls)
But this gives me the following content of python_func_calls:
['print_a', 'print_b']
I had thought there would be 4 entries in the list, as decorated functions were called 4 times.
CodePudding user response:
You need to create a new function and return that from the decorator. Inside this function, call the passed in wrapped function. For example:
python_func_calls = []
def log_func_call(func):
def wrapped():
python_func_calls.append(func.__name__)
func()
return wrapped
@log_func_call
def print_a():
print('I am the a function...')
@log_func_call
def print_b():
print('I am the b function...')
print_a()
print_b()
print_b()
print_a()
print(python_func_calls)
This gives python_func_calls as:
['print_a', 'print_b', 'print_b', 'print_a']
The reason this works is that the returned function replaces the wrapped function. So it gets called each time, rather than just when the decorator is created.
CodePudding user response:
The decorator is called at the function definition so twice total:
python_func_calls = []
def log_func_call(func):
python_func_calls.append(func.__name__)
return func
@log_func_call #first call
def print_a():
print('I am the a function...')
@log_func_call #second call
def print_b():
print('I am the b function...')
print_a() #decorator not called
print_b() #decorator not called
print_b() #decorator not called
print_a() #decorator not called
print(python_func_calls)
So despite 4 function calls there are only 2 decorator calls.
