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}
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.