Elegant way to unpack limited dict values into local variables in Python
Question:
I’m looking for an elegant way to extract some values from a Python dict into local values.
Something equivalent to this, but cleaner for a longer list of values, and for longer key/variable names:
d = { 'foo': 1, 'bar': 2, 'extra': 3 }
foo, bar = d['foo'], d['bar']
I was originally hoping for something like the following:
foo, bar = d.get_tuple('foo', 'bar')
I can easily write a function which isn’t bad:
def get_selected_values(d, *args):
return [d[arg] for arg in args]
foo, bar = get_selected_values(d, 'foo', 'bar')
But I keep having the sneaking suspicion that there is some other builtin way.
Answers:
Somewhat horrible, but:
globals().update((k, v) for k, v in d.iteritems() if k in ['foo', 'bar'])
Note, that while this is possible – it’s something you don’t really want to be doing as you’ll be polluting a namespace that should just be left inside the dict
itself…
Well, if you know the names ahead of time, you can just do as you suggest.
If you don’t know them ahead of time, then stick with using the dict – that’s what they’re for.
If you insist, an alternative would be:
varobj = object()
for k,v in d.iteritems(): setattr(varobj,k,v)
After which, keys will be variables on varobj
.
You can do something like
foo, bar = map(d.get, ('foo', 'bar'))
or
foo, bar = itemgetter('foo', 'bar')(d)
This may save some typing, but essentially is the same as what you are doing (which is a good thing).
The elegant solution:
d = { "foo": 123, "bar": 456, None: 789 }
foo, bar, baz = d.values() # 123, 456, 789
Notice that keys are not used, so be sure to get the order of your variables right, i.e. they must match the order that the keys were inserted into the map (this ordering is guaranteed since Python 3.6). If in doubt about ordering, use the other methods.
If you’re looking for elegance with performance across python versions, sadly I don’t think you’re gonna get any better than:
unpack = lambda a,b,c,**kw: (a,b,c) # static
d = dict( a=1, b=2, c=3, d=4, e=5 )
a,b,c = unpack(**d)
working examples:
>>> unpack = lambda a,b,c,**kw: (a,b,c)
>>> d = dict( a=1, b=2, c=3, d=4, e=5, f=6, g=7 )
>>> a,b,c = unpack(**d)
>>>
>>> unpack(**d)
(1, 2, 3)
you can also unpack the difference that would otherwise be discarded:
>>> unpackextra = lambda a,b,c,**kw: (a,b,c,kw)
>>> a,b,c,extra = unpackextra(**d)
>>>
>>> unpackextra(**d)
(1, 2, 3, {'f': 6, 'd': 4, 'e': 5, 'g': 7})
arguments are static though, so the use case should be specific to whatever your intents are. 😉
>>> unpack2 = lambda a,b,c,d,e,f,**kw: (a,b,c,d,e,f) # static
>>>
>>> unpack2(**d)
(1, 2, 3, 4, 5, 6)
>>>
I’m looking for an elegant way to extract some values from a Python dict into local values.
Something equivalent to this, but cleaner for a longer list of values, and for longer key/variable names:
d = { 'foo': 1, 'bar': 2, 'extra': 3 }
foo, bar = d['foo'], d['bar']
I was originally hoping for something like the following:
foo, bar = d.get_tuple('foo', 'bar')
I can easily write a function which isn’t bad:
def get_selected_values(d, *args):
return [d[arg] for arg in args]
foo, bar = get_selected_values(d, 'foo', 'bar')
But I keep having the sneaking suspicion that there is some other builtin way.
Somewhat horrible, but:
globals().update((k, v) for k, v in d.iteritems() if k in ['foo', 'bar'])
Note, that while this is possible – it’s something you don’t really want to be doing as you’ll be polluting a namespace that should just be left inside the dict
itself…
Well, if you know the names ahead of time, you can just do as you suggest.
If you don’t know them ahead of time, then stick with using the dict – that’s what they’re for.
If you insist, an alternative would be:
varobj = object()
for k,v in d.iteritems(): setattr(varobj,k,v)
After which, keys will be variables on varobj
.
You can do something like
foo, bar = map(d.get, ('foo', 'bar'))
or
foo, bar = itemgetter('foo', 'bar')(d)
This may save some typing, but essentially is the same as what you are doing (which is a good thing).
The elegant solution:
d = { "foo": 123, "bar": 456, None: 789 }
foo, bar, baz = d.values() # 123, 456, 789
Notice that keys are not used, so be sure to get the order of your variables right, i.e. they must match the order that the keys were inserted into the map (this ordering is guaranteed since Python 3.6). If in doubt about ordering, use the other methods.
If you’re looking for elegance with performance across python versions, sadly I don’t think you’re gonna get any better than:
unpack = lambda a,b,c,**kw: (a,b,c) # static
d = dict( a=1, b=2, c=3, d=4, e=5 )
a,b,c = unpack(**d)
working examples:
>>> unpack = lambda a,b,c,**kw: (a,b,c)
>>> d = dict( a=1, b=2, c=3, d=4, e=5, f=6, g=7 )
>>> a,b,c = unpack(**d)
>>>
>>> unpack(**d)
(1, 2, 3)
you can also unpack the difference that would otherwise be discarded:
>>> unpackextra = lambda a,b,c,**kw: (a,b,c,kw)
>>> a,b,c,extra = unpackextra(**d)
>>>
>>> unpackextra(**d)
(1, 2, 3, {'f': 6, 'd': 4, 'e': 5, 'g': 7})
arguments are static though, so the use case should be specific to whatever your intents are. 😉
>>> unpack2 = lambda a,b,c,d,e,f,**kw: (a,b,c,d,e,f) # static
>>>
>>> unpack2(**d)
(1, 2, 3, 4, 5, 6)
>>>