Divide a dictionary into variables
Question:
I am studying Python and currently going through some more learning with dictionaries.
I was wondering;
If I have a dictionary like: d = {'key_1': 'value_a', 'key_2': 'value_b'}
and I want separate/divide this dictionary into variables where each variable is a key from the dictionary and each variables value is the value of that key in the dictionary.
What would be the best pythonic way to achieve this?
d = {'key_1': 'value_a', 'key_2': 'value_b'}
#perform the command and get
key_1 = 'value_a'
key_2 = 'value_b'
I tried: key_1, key_2 = d
but it did not work.
Basically I am seeking expert’s wisdom to find out if there is a better way to reduce 2 lines of code into one.
Note: This is not a dynamic variable creation.
Answers:
Problem is that dicts are unordered, so you can’t use simple unpacking of d.values()
. You could of course first sort the dict by key, then unpack the values:
# Note: in python 3, items() functions as iteritems() did
# in older versions of Python; use it instead
ds = sorted(d.iteritems())
name0, name1, name2..., namen = [v[1] for v in ds]
You could also, at least within an object, do something like:
for k, v in dict.iteritems():
setattr(self, k, v)
Additionally, as I mentioned in the comment above, if you can get all your logic that needs your unpacked dictionary as variables in to a function, you could do:
def func(**kwargs):
# Do stuff with labeled args
func(**d)
It’s not recommended to ever declare variables dynamically, because it becomes very difficult to find the source of a variable name. That said, it’s possible to hack together a solution Dynamic variable name in python but I wouldn’t recommend it. Probably better off using a plain old dictionary.
I actually have a usecase, where i pull all the arguments of an __init__
method into the self namespace on object construction:
vars(self).update(somedict)
The vars function gets you a dict of the “namespace” associated with the object passed. However, this will not work with locals in a function, due to CPython implementation details. So it’s not supposed to work on all interpreters.
For global namespace you would substitute vars(self)
with globals()
, but this is really a sign that something is wrong with your logic. As said, for local variables this won’t work anyways (It’ll NameError
even if you assigned a value to the dict).
You can do this, if you’re brave:
for k, v in d.items():
locals()[k] = v
But being brave might not be enough – you might also have to be reckless etc.
If you want to be a reckless hero like @ecatmur, you can do this:
locals().update(d)
But now that OP has updated his question and answered comments, it seems, this isn’t what he really wants to do. Just for the record: There are good reasons for dynamically creating variables – even if everyone here agrees that it’s not pythonic. A lot of interpreter style problems can be solved neetly with dynamic altering of your scope. Just do this in a controlled fashion. And… uh, don’t deploy this to some production site 😉
A solution which has not been mentionned before would be
dictget = lambda d, *k: [d[i] for i in k]
and then use it:
key_1, key_2 = dictget(d, 'key_1', 'key_2')
whose advantage is that it is quite readable even with more variables to be retrieved.
Even more readable, however, would be a “real” function such as
def dictget(d, *k):
"""Get the values corresponding to the given keys in the provided dict."""
return [d[i] for i in k]
# or maybe
return (d[i] for i in k) # if we suppose that we have bigger sets of result
# or, equivalent to this
for i in k:
yield d[i]
which as well supports commenting with a docstring and is to be preferred.
i think this should solve your problem
d = {'key_1': 'value_a', 'key_2': 'value_b'}
for k,v in d.items():
exec '%s=%s'%(k,v)
var1, var2 = (lambda key1, key2: (key1, key2))(**d)
If you want to give anyone reading your code a headache you can use anonymous function to unpack values like this.
The existing answers will work, but they’re all essentially re-implementing a function that already exists in the Python standard library: operator.itemgetter()
From the docs:
Return a callable object that fetches item from its operand using the operand’s __getitem__() method. If multiple items are specified, returns a tuple of lookup values. For example:
After f = itemgetter(2), the call f(r) returns r[2].
After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3]).
In other words, your destructured dict assignment becomes something like:
from operator import itemgetter
d = {'key_1': 'value_a', 'key_2': 'value_b'}
key_1, key_2 = itemgetter('key_1', 'key_2')(d)
# prints "Key 1: value_a, Key 2: value_b"
print("Key 1: {}, Key 2: {}".format(key_1, key_2))
Here is a solution that uses Python’s inspect module on the calling stack frame to determine how to extract the right values from a supplied dictionary. Right now the only check is to make sure that there is a value available for each of the output variables, but feel free to add additional checks if you need them.
import inspect
def update(src):
result = []
cprev = inspect.currentframe().f_back
#print(cprev.f_code.co_names)
for v in cprev.f_code.co_names[1:]:
if src is cprev.f_locals[v]: continue
if v in src:
result.append(src[v])
else:
raise NameError(v + " has no source for update")
return result
Usage looks like this:
src={'a': 1, 'b': 2, 'c': 3}
a,b,c = update(src)
@glglgl’s answer is not most voted, that answer worked for me,
solution1={'variable': np.array([75, 74]), 'function': 0}
def dict_get(d, *k):
for i in k:
yield d[i]
variables, obj_func = dict_get(solution1, 'variable', 'function')
a, b=variables
print(a)
reference: @glglgl
I am studying Python and currently going through some more learning with dictionaries.
I was wondering;
If I have a dictionary like: d = {'key_1': 'value_a', 'key_2': 'value_b'}
and I want separate/divide this dictionary into variables where each variable is a key from the dictionary and each variables value is the value of that key in the dictionary.
What would be the best pythonic way to achieve this?
d = {'key_1': 'value_a', 'key_2': 'value_b'}
#perform the command and get
key_1 = 'value_a'
key_2 = 'value_b'
I tried: key_1, key_2 = d
but it did not work.
Basically I am seeking expert’s wisdom to find out if there is a better way to reduce 2 lines of code into one.
Note: This is not a dynamic variable creation.
Problem is that dicts are unordered, so you can’t use simple unpacking of d.values()
. You could of course first sort the dict by key, then unpack the values:
# Note: in python 3, items() functions as iteritems() did
# in older versions of Python; use it instead
ds = sorted(d.iteritems())
name0, name1, name2..., namen = [v[1] for v in ds]
You could also, at least within an object, do something like:
for k, v in dict.iteritems():
setattr(self, k, v)
Additionally, as I mentioned in the comment above, if you can get all your logic that needs your unpacked dictionary as variables in to a function, you could do:
def func(**kwargs):
# Do stuff with labeled args
func(**d)
It’s not recommended to ever declare variables dynamically, because it becomes very difficult to find the source of a variable name. That said, it’s possible to hack together a solution Dynamic variable name in python but I wouldn’t recommend it. Probably better off using a plain old dictionary.
I actually have a usecase, where i pull all the arguments of an __init__
method into the self namespace on object construction:
vars(self).update(somedict)
The vars function gets you a dict of the “namespace” associated with the object passed. However, this will not work with locals in a function, due to CPython implementation details. So it’s not supposed to work on all interpreters.
For global namespace you would substitute vars(self)
with globals()
, but this is really a sign that something is wrong with your logic. As said, for local variables this won’t work anyways (It’ll NameError
even if you assigned a value to the dict).
You can do this, if you’re brave:
for k, v in d.items():
locals()[k] = v
But being brave might not be enough – you might also have to be reckless etc.
If you want to be a reckless hero like @ecatmur, you can do this:
locals().update(d)
But now that OP has updated his question and answered comments, it seems, this isn’t what he really wants to do. Just for the record: There are good reasons for dynamically creating variables – even if everyone here agrees that it’s not pythonic. A lot of interpreter style problems can be solved neetly with dynamic altering of your scope. Just do this in a controlled fashion. And… uh, don’t deploy this to some production site 😉
A solution which has not been mentionned before would be
dictget = lambda d, *k: [d[i] for i in k]
and then use it:
key_1, key_2 = dictget(d, 'key_1', 'key_2')
whose advantage is that it is quite readable even with more variables to be retrieved.
Even more readable, however, would be a “real” function such as
def dictget(d, *k):
"""Get the values corresponding to the given keys in the provided dict."""
return [d[i] for i in k]
# or maybe
return (d[i] for i in k) # if we suppose that we have bigger sets of result
# or, equivalent to this
for i in k:
yield d[i]
which as well supports commenting with a docstring and is to be preferred.
i think this should solve your problem
d = {'key_1': 'value_a', 'key_2': 'value_b'}
for k,v in d.items():
exec '%s=%s'%(k,v)
var1, var2 = (lambda key1, key2: (key1, key2))(**d)
If you want to give anyone reading your code a headache you can use anonymous function to unpack values like this.
The existing answers will work, but they’re all essentially re-implementing a function that already exists in the Python standard library: operator.itemgetter()
From the docs:
Return a callable object that fetches item from its operand using the operand’s __getitem__() method. If multiple items are specified, returns a tuple of lookup values. For example:
After f = itemgetter(2), the call f(r) returns r[2].
After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3]).
In other words, your destructured dict assignment becomes something like:
from operator import itemgetter
d = {'key_1': 'value_a', 'key_2': 'value_b'}
key_1, key_2 = itemgetter('key_1', 'key_2')(d)
# prints "Key 1: value_a, Key 2: value_b"
print("Key 1: {}, Key 2: {}".format(key_1, key_2))
Here is a solution that uses Python’s inspect module on the calling stack frame to determine how to extract the right values from a supplied dictionary. Right now the only check is to make sure that there is a value available for each of the output variables, but feel free to add additional checks if you need them.
import inspect
def update(src):
result = []
cprev = inspect.currentframe().f_back
#print(cprev.f_code.co_names)
for v in cprev.f_code.co_names[1:]:
if src is cprev.f_locals[v]: continue
if v in src:
result.append(src[v])
else:
raise NameError(v + " has no source for update")
return result
Usage looks like this:
src={'a': 1, 'b': 2, 'c': 3}
a,b,c = update(src)
@glglgl’s answer is not most voted, that answer worked for me,
solution1={'variable': np.array([75, 74]), 'function': 0}
def dict_get(d, *k):
for i in k:
yield d[i]
variables, obj_func = dict_get(solution1, 'variable', 'function')
a, b=variables
print(a)
reference: @glglgl