Home > Net >  Python decorator not acting as expected
Python decorator not acting as expected

Time:01-25

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.

  •  Tags:  
  • Related