简体   繁体   中英

When unpacking a dictionary to pass as keyword arguments, how can I map a key to a differently named keyword argument?

Let's say I have some code:

def test(a, b, **kwargs):
    print(kwargs)

l = {'a': 0, 'c': 1, 'foo': 2, 'bar': 3}

What I want to do is to pass the unpacked dictionary into the function, but map its key c to parameter b , while preserving any other keys that do not directly correspond to a parameter in kwargs, so the function should output {'foo': 2, 'bar': 3} . If I do test(b=l['c'], **l) , the key c remains in kwargs, and output looks like this: {'foo': 2, 'bar': 3, 'c': 1} . test(**l) , obviously, crashes with an error - test() missing 1 required positional argument: 'b' .

How is it possible to do this?

What you want is not possible. Just manipulate your dictionary before passing it in to the call:

b = l.pop('c')
test(b=b, **l)

or

l['b'] = l.pop('c')
test(**l)

or

test(**{'b' if k == 'c' else k: v for k, v in l.items()})

all of which pass in a dictionary to the ** syntax that does not have a c key in it.

For a more sophisticated cases when there would be a need to map/adjust multiple keys without mutating the initial input dictionary - consider using decorators :

import functools

def map_keys_decorator():
    def decorate(func):

        @functools.wraps(func)
        def mapped_test(*args, **kwargs):
            kwargs = dict(kwargs)
            kwargs['b'] = kwargs.pop('c')   # here you can add another additonal logic
            return func(**kwargs)
        return mapped_test

    return decorate

@map_keys_decorator()
def test(a, b, **kwargs):
    print(kwargs)

l = {'a': 0, 'c': 1, 'foo': 2, 'bar': 3}
test(**l)    # {'foo': 2, 'bar': 3}

print(l)     # {'foo': 2, 'bar': 3, 'c': 1, 'a': 0}

Remove key c and add b :

def test(a, b, **kwargs):
    print(kwargs)

l = {'a': 0, 'c': 1, 'foo': 2, 'bar': 3}

l2 = l.copy()
l2['b'] = l2['c']
del l2['c']

test(**l2)

Output:

{'foo': 2, 'bar': 3}

https://repl.it/NXd2/0

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM