Nosail
Nosail

Reputation: 471

Unable to pass an object using **kwargs

I have been trying to get a handle on *args and **kwargs keywords.

I have been playing around with the following code:

user1 = {
    'name': 'Gandalf',
    'wizard': True
}

def authenticated(func):
    def inner_func(*args, **kwargs):
        print(kwargs)
        if kwargs['wizard']:
            print('(:**********:)')
        return func(*args, **kwargs)    
    return inner_func
    
    
@authenticated
def message_friends(user):
    print(user)
    print(user.name)
    print('message has been sent')
    print(user.items()) # every key-value pair in a dictionary is a tuple
     
    for key, value in user.items(): 
        print(key, value)
        print (type((key, value)))
    print('**********')

message_friends(**user1)

I receive the following error. But I am not certain why. Can someone point me in the right direction.

{'name': 'Gandalf', 'wizard': True}
(:**********:)
Traceback (most recent call last):
  File "main.py", line 31, in <module>
    message_friends(**user1) #closure is run
  File "main.py", line 12, in inner_func
    return func(*args, **kwargs)    
TypeError: message_friends() got an unexpected keyword argument 'name'

Upvotes: 0

Views: 413

Answers (1)

TheEagle
TheEagle

Reputation: 5992

**user1 unpacks the dictionary into keyword arguments having the dictionary's keys as names and the values as values. So, for every key of your dictionary, you need an argument with the same name in your function. This code works:

user1 = {
    'name': 'Gandalf',
    'wizard': True
}

def authenticated(func):
    def inner_func(*args, **kwargs):
        print(kwargs)
        if kwargs['wizard']:
            print('(:**********:)')
        return func(*args, **kwargs)    
    return inner_func
    
    
@authenticated
def message_friends(name, wizard):
    print(name)
    print(wizard)
    print('message has been sent')
    print('**********')

message_friends(**user1)

If you don't want hard coded variable names, you can re-pack the dictionary in the message_user function:

user1 = {
    'name': 'Gandalf',
    'wizard': True
}

def authenticated(func):
    def inner_func(*args, **kwargs):
        print(kwargs)
        if kwargs['wizard']:
            print('(:**********:)')
        return func(*args, **kwargs)    
    return inner_func


@authenticated
def message_friends(**user):
    print(user)
    print(user["name"])
    print('message has been sent')
    print(user.items()) # every key-value pair in a dictionary is a tuple

    for key, value in user.items(): 
        print(key, value)
        print(type(key), type(value))
    print('**********')

message_friends(**user1)

Upvotes: 1

Related Questions