简体   繁体   中英

Pass same keyword argument to a function twice

This is two questions, and I'd be happy with either being answered (unless one method is preferred to another).

I have a function, say

def my_func(a, b, c, d = None):
    print(a)
    print(f"I like {b}")
    print(f"I am {c}")
    if d:
        print(d)

I have a dictionary of keywords my_dict = {'a': 'Hello', 'b': 'Dogs', 'c': 'Happy', 'd': 10} which are always passed as inputs to the function my_func(**kwargs).

My questions are:

  1. If I want to input a different value, say a='Goodbye', is there a way I can input the same argument twice overriding the first entry with the second instance of it?
  2. Alternatively, is there something comparable to my_dict.update({'a': 'Hello'}) that won't change the values in the dictionary permanently, but will let me pass in a different value for a specific keyword?

I know I can create a new dictionary and pass that in, but I think it would be cleaner if I could do it without needing to do this (though feel free to correct me if I'm wrong!).

Edit: I'm using Python 3.8.

On Python 3.5 and up, you can unpack my_dict into a new dict and override the 'a' entry:

my_func(**{**my_dict, 'a': 'Goodbye'})

On Python 3.9 and up, you can use the | operator to create a new dict by merging entries from two dicts. Values for duplicated keys will be taken from the second dict:

my_func(**my_dict | {'a': 'Goodbye'})

Since Python 3.3, you can use collections.ChainMap :

A ChainMap groups multiple dicts or other mappings together to create a single, updateable view.[...]

Lookups search the underlying mappings successively until a key is found. [...] A ChainMap incorporates the underlying mappings by reference. So, if one of the underlying mappings gets updated, those changes will be reflected in ChainMap.

So, your code could be:

from collections import ChainMap

def my_func(a, b, c):
    print(a)
    print(f"I like {b}")
    print(f"I am {c}")
    
my_dict = {'a': 'Hello', 'b': 'Dogs', 'c': 'Happy'} 
new = {'a':'Goodbye' }

my_func(**ChainMap(new, my_dict))
#Goodbye
#I like Dogs
#I am Happy

Note that new must come before my_dict , as the value will be taken from the first dict that contains the key.

Since Python 3.10, you can use the | operator:

d | other

Create a new dictionary with the merged keys and values of d and other, which must both be dictionaries. The values of other take priority when d and other share keys.

So, you could call your function with

my_func(**(my_dict | new))

Note that in this case, new must come after `mydict.

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