11

I have two dictionaries:

SP = dict{'key1': 'value1','key2': 'value2'}
CP = dict{'key1': 'value1','key2': 'value2'}

I have a function that would like to take those two dictionaries as inputs, but I don't know how to do that.

I'd tried:

def test(**SP,**CP):
    print SP.keys(),CP.keys()

test(**SP,**CP)

The real function will be more complicated with lots of modification of two dictionaries. But the simple test function doesn't work for me :(

Gabriel
  • 40,504
  • 73
  • 230
  • 404
scinthx
  • 129
  • 1
  • 1
  • 3

10 Answers10

9

If you just want to take two dictionaries as separate arguments, just do

def test(SP, CP):
    print SP.keys(),CP.keys()

test(SP, CP)

You only use ** when you want to pass the individual key/value pairs of a dictionary as separate keyword arguments. If you're passing the whole dictionary as a single argument, you just pass it, the same way you would any other argument value.

BrenBarn
  • 242,874
  • 37
  • 412
  • 384
6

When you want to pass two different dictionaries to a function that both contains arguments for your function you should first merge the two dictionaries.

For example:

dicA = {'spam':3, 'egg':4}
dicB = {'bacon':5, 'tomato':6}

def test(spam,tomato,**kwargs):
    print spam,tomato

#you cannot use:
#test(**dicA, **dicB)

So you have to merge the two dictionaries. There are several options for this: see How to merge two Python dictionaries in a single expression?

dicC = dicA.copy()
dicC.update(dicB)

#so now one can use:
test(**dicC)

>> 3 6
Community
  • 1
  • 1
JLT
  • 712
  • 9
  • 15
6

You can combine both dictionaries (SP and CP) in a single one using the dict constructor.

test(**dict(SP,**CP))
vjerez
  • 119
  • 1
  • 5
1

Why it doesn't work:

In Python the "**" prefix in the arguments is to make one argument capture several other ones. For example:

SP = {'key1': 'value1','key2': 'value2'}

def test(**kwargs):              #you don't have to name it "kwargs" but that is
    print(kwargs)                #the usual denomination


test(**SP)
test(key1='value1', key2='value2')

The two call on the test function are exactly the same

Defining a function with two ** arguments would be ambiguous, so your interpreter won't accept it, but you don't need it.

How to make it work:

It is not necessary to use ** when working with normal dictionary arguments: in that case you can simply do:

SP = {'key1': 'value1','key2': 'value2'}
CP = {'key1': 'value1','key2': 'value2'}

def test(SP,CP):
    print(SP)
    print(CP)

test(SP,CP)

Dictionaries are objects that you can directly use in your arguments. The only point where you need to be careful is not to modify directly the dictionary in argument if you want to keep the original dictionnary.

Anne Aunyme
  • 506
  • 4
  • 14
0

Use *args to take multiple arguments.

SP={'key1':'value1','key2':'value2'}  `dict{'key1':'value1','key2':'value2'}` 
CP={'key1':'value1','key2':'value2'}

def test(*args):
    for arg in args:
        print arg.keys(),

test(SP,CP)
['key2', 'key1'] ['key2', 'key1']
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
0
def merge(*d):
   r={}
   for x in d:r.update(x)
   return r

d1={'a': 1, 'b': 2}
d2={'y': 4, 'x': 3}

def f(**k): print(k)

f(**merge(d1,d2))   # you're on your own if keys repeat unintentionally

gives {'a': 1, 'y': 4, 'b': 2, 'x': 3}

user6336835
  • 77
  • 1
  • 2
0

If you want to avoid combining the dictionaries, then provide them as arguments rather than keyword arguments, and set their defaults to something (such as None), and convert None to {} and otherwise copy the dictionary.

SP = {'key1': 'value1', 'key2': 'value2'}
CP = {'key1': 'value3', 'key2': 'value4'}

def test(SP=None, CP=None):
    SP = {} if SP is None else SP.copy()
    CP = {} if CP is None else CP.copy()
    # Now use SP and CP as keyword arguments to other functions
    foo(**SP)
    baz(**CP)

def foo(**kws):
    print(kws.items())

def baz(**kws):
    print(kws)

test(SP=SP)
test(CP=CP)
test(SP, CP)

I often do this when passing keyword arguments to different plotting functions called within my function, and I send different dictionaries of keyword arguments to these plotting functions.

Charlie Brummitt
  • 651
  • 6
  • 11
0

TLDR: Pass a dictionary of dictionaries

I found myself with same problem and i can't merge dictionaries because I wanted to keep the contents of each dictionary apart inside the called function. Solution I found is to use a nested dictionary.

    args = {}
    args['SP'] = dict{'key1': 'value1','key2': 'value2'}
    args['CP'] = dict{'key1': 'value1','key2': 'value2'}

    test(**args)

    def test (**kwargs):
        arg_sp = kwargs.get('SP')
        arg_cp = kwargs.get('CP')
physicist
  • 844
  • 1
  • 12
  • 24
0

As usually the kwargs is used to add countless function parameters, therefore it is somehow unusual to use two kwargs at the same time. But another way around, two dictionaries can be parameterized as usual parameters. Thus a little bit of change in the code snipet might be helpful:

SP = {'key1': 'value1','key2': 'value2'}
CP = {'key1': 'value1','key2': 'value2'}
def test(SP,CP):
    print(SP.keys(),CP.keys())

test(SP,CP)

Output: dict_keys(['key1', 'key2']) dict_keys(['key1', 'key2'])

0

You can pass only a single dictionary to the **kwargs but if you want to pass a second dictionary you can simply pass it as a simple variable e.g.

SP = dict({"key1": "value1", "key2": "value2"})
CP = dict({"key1": "value1", "key2": "value2"})


def test(SP, **CP):
    # print(SP.keys(), CP.keys())
    print("Keys of Dictionary 1: ", SP.keys())
    print("Keys of Dictionary 2: ", CP.keys())


test(SP, **CP)
asad jani
  • 51
  • 6