Chidananda Nayak
Chidananda Nayak

Reputation: 1201

Python decorater TypeError in **kwargs

I am trying to understand python decorator in depth

def lol(func):
    def wrapper(*args,**kwargs):
        print(*args)
        print(**kwargs)
        return func(*args,**kwargs)
    return wrapper

@lol
def greet(name,lol,l):
    return f'{name}:{lol}:{l}'

greet('tom',"dick",l="harry")

so when i give only positional args like greet('tom',"dick","harry") this function works but when i give keyword arguments followed by positional argument greet('tom',"dick",l="harry") it gives me error.

TypeError: 'l' is an invalid keyword argument for this function

but when i re-write my decorator like this

def lol(func):
    def wrapper(*args,**kwargs):
        print(*args)
        print(**kwargs)
        return wrapper(*args,**kwargs)
    return func

It works fine. I am little confused what is happening. Would be great if somebody explains it no matter how silly is the cause. Thank you.

Upvotes: 1

Views: 83

Answers (1)

ShadowRanger
ShadowRanger

Reputation: 155418

You don't want to do:

    print(**kwargs)

That tries to expand the keyword arguments as keyword arguments to print, so in your use case, it's like you typed print(l="harry"), which is clearly nonsensical (print doesn't take an argument named l). Just do:

    print(kwargs)

to see the dict of keyword arguments received. Similarly, print(args) is likely to be a better solution than print(*args) as it will print reprs, which typically tell you more about the arguments for debugging purposes.

The reason your second approach "works fine" is that it doesn't decorate anything. You make wrapper, throw it away, then return the original func, so the original func is called, and print(**kwargs) never occurs.

Upvotes: 1

Related Questions