Unpacking multiple dictionaries in a function?

M

Martin De Kauwe

Hi,

Is there a better way to unpack more than one dictionary in a function
than...

def unpack_dicts(f):
def wrapper(*old_dicts):
dict={}
for d in old_dicts:
dict.update(d)
return f(**dict)
return wrapper

@unpack_dicts
def some_func(a=None, b=None, c=None):
print a, b, c

d1 = {'a': 20.0, 'b': '-1'}
d2 = {'c': 33.0}

some_func(d1, d2)

thanks
 
P

Peter Otten

Martin De Kauwe wrote:

Is there a better way to unpack more than one dictionary in a function
than...

def unpack_dicts(f):
def wrapper(*old_dicts):
dict={}
for d in old_dicts:
dict.update(d)
return f(**dict)
return wrapper

@unpack_dicts
def some_func(a=None, b=None, c=None):
print a, b, c

d1 = {'a': 20.0, 'b': '-1'}
d2 = {'c': 33.0}

some_func(d1, d2)

thanks

If you had shown a solution involving
dicts = [dict(a=1, b=2, c=3), dict(a=10, b=20, z=40), dict(a=100, t=500)]
reduce(lambda a, d: a.update(d) or a, dicts, {})
{'a': 100, 'c': 3, 'b': 20, 't': 500, 'z': 40}

I would have pointed out your approach. So yes, I think you have already
found the best solution.
 
C

Chris Rebert

Hi,

Is there a better way to unpack more than one dictionary in a function
than...

def unpack_dicts(f):
   def wrapper(*old_dicts):
       dict={}

I wouldn't call the variable "dict" since that clashes with the name
of the built-in type.
       for d in old_dicts:
           dict.update(d)
       return f(**dict)
   return wrapper

@unpack_dicts
def some_func(a=None, b=None, c=None):
   print a, b, c

d1 = {'a': 20.0, 'b': '-1'}
d2 = {'c': 33.0}

some_func(d1, d2)

Aside from slight variants on this approach, no, there's not really a
better way to do it.
There's no built-in way to do it because different users might want
different dict merging algorithms, such as:
- multiple values for the same key is an error
- multiple values for the same key are combined into a list/set of values
- entries in earlier dicts clobber those in later dicts
- entries in later dicts clobber those in earlier dicts

Python has "In the face of ambiguity, refuse the temptation to guess."
and "Explicit is better than implicit." among its design principles,
and hence provides no default solution here, requiring the user to
specify the behavior explicitly by doing the merging themselves.

Cheers,
Chris
 
P

Paul Rubin

Martin De Kauwe said:
def wrapper(*old_dicts):
dict={}
for d in old_dicts:
dict.update(d)
return f(**dict)

Untested:

from itertools import chain
def wrapper(*old_dicts):
return f(**dict(chain(d.iteritems() for d in old_dicts)))
 
P

Peter Otten

Paul said:
Untested:

from itertools import chain
def wrapper(*old_dicts):
return f(**dict(chain(d.iteritems() for d in old_dicts)))

I think you need chain.from_iterable() instead of chain().
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top