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.

Asked By: Phil

||

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)
Answered By: Silas Ray

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.

Answered By: Emmett Butler

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).

Answered By: Jonas Schäfer

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 😉

Answered By: Daren Thomas

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.

Answered By: glglgl

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)
Answered By: Tanu
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.

Answered By: Devilholk

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))
Answered By: mintchkin

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)
Answered By: user1637146

@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

Answered By: itssoelif
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.