Search code examples
pythondecoratorpython-decorators

How to access individual arguments of args passed to decorated function


I am trying to decorate 5 functions with an exception handling function. Each decorated function is to accept a differing number of parameters but all will have one important parameter in common, fname. I'd like to use that common parameter, as example shows below.

This comes close but I can't get to fname:

def mydeco(func):
    
    def wrapper(*args, **kwargs):
    
        print(args)
        #print(fname) <== this fails as well;
        #Unwrapping args gives 'SyntaxError: can't use starred expression here'
               
        try:
            print('Before func')
            answer = func(*args,**kwargs)
            print('after func in wrapper')
            if answer == 2:
                print(f"Great job {fname}")
        except Exception as e:
            print('blah', e)
    
    return wrapper


@mydeco
def long(fname, lname):
    print(f"hello {fname} {lname}")
    return 2

@mydeco
def short(fname):
    print(f"hello {fname}")



short('Bob')
long('Bob', 'Smith')

('Bob',)
Before func
hello Bob
after func in wrapper
('Bob', 'Smith')
Before func
hello Bob Smith
after func in wrapper
blah name 'fname' is not defined

Am I way off?


Solution

  • The wrapper function's parameters are *args and **kwargs. The lname and fname parameters are not defined in wrapper outside of the inner functions.

    In this function call

    long('Bob', 'Smith')

    the positional arguments are passed as an *args tuple. They can be accessed in wrapper as follows: args[0] and args[1].

    Alternatively, if you change the function call to

    long(fname = 'Bob', lname = 'Smith')

    then the keyword arguments will be passed as a **kwargs dictionary. They can be accessed as follows: kwargs['fname'] and kwargs['lname'].