Kodeclik Blog
Dictionary unpacking into variables
Let us suppose you create a dictionary mapping season names to numbers, like so:
seasons_to_vals = {}
seasons_to_vals['Spring'] = 1
seasons_to_vals['Summer'] = 2
seasons_to_vals['Fall'] = 3
seasons_to_vals['Winter'] = 4
We wish to unpack the dictionary into individual variables like so:
Spring = 1
Summer = 2
Fall = 3
Winter = 4
We can do this in the following manner:
Spring = seasons_to_vals['Spring']
This will cause the creation of the variable “Spring” and will give a value of 1. We can extend it to multiple variables, like so (if you use one of the below lines, you can delete the lines above that line):
Spring = seasons_to_vals['Spring']
Spring, Summer = seasons_to_vals['Spring'],
seasons_to_vals['Summer']
Spring, Summer, Fall = seasons_to_vals['Spring'],
seasons_to_vals['Summer'],
seasons_to_vals['Fall']
Spring, Summer, Fall, Winter = seasons_to_vals['Spring'],
seasons_to_vals['Summer'],
seasons_to_vals['Fall'],
seasons_to_vals['Winter']
The problem with this approach is that it is un-elegant. First, it requires you to know the keys and because dictionaries are unordered it requires you to be very careful in how these variables are equated to their values.
Method 1: Use the exec() function to make assignments by iterating over the dictionary
The first approach we will see is to iterate over the dictionary entries and for each step of the iteration use the exec() function to generate a variable assignment.
seasons_to_vals = {}
seasons_to_vals['Spring'] = 1
seasons_to_vals['Summer'] = 2
seasons_to_vals['Fall'] = 3
seasons_to_vals['Winter'] = 4
for (k,v) in seasons_to_vals.items():
exec(f'{k} = {v}')
print(Spring)
print(Summer)
print(Fall)
print(Winter)
In the above code, we use the items() method on our dictionary which returns a list of (key, value) pairs stored in variables (k,v). Inside the loop, we use “exec” to make assignments of values to keys. This program when run will yield:
1
2
3
4
indicating that the variables have been successfully created.
Method 2: Use the locals().update() method or globals().update() method to directly update the variable symbol table
A symbol table is a table mapping variables to values and something that is maintained internally by your Python interpreter. This mapping is itself stored in a dictionary object! It is not something that the regular programmer needs to worry about but is nevertheless available for inspection (and modification). There are two symbol tables: locals and globals. The locals table operates at a function or module level or in an interactive shell environment (like how we are doing now). The globals table keeps track of variables at the global scope level. For our purposes they are the same but do keep in mind that inside a function or module, the locals table will be different from the globals table.
Because these symbol tables are themselves dictionaries, we can just pass our dictionary to the update() method on either the locals or globals table and it will do the needful, i.e., create mappings from the desired variables to values. Here is how that works:
print("BEFORE:")
print(locals())
seasons_to_vals = {}
seasons_to_vals['Spring'] = 1
seasons_to_vals['Summer'] = 2
seasons_to_vals['Fall'] = 3
seasons_to_vals['Winter'] = 4
print("AFTER:")
locals().update(seasons_to_vals)
print(locals())
The output is (your output might vary slightly):
BEFORE:
{'__name__': '__main__',
'__doc__': None,
'__package__': None,
'__loader__':
<_frozen_importlib_external.SourceFileLoader object at 0x7fb2b1ccb7c0>,
'__spec__': None,
'__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>,
'__file__': 'main.py',
'__cached__': None}
AFTER:
{'__name__': '__main__',
'__doc__': None,
'__package__': None,
'__loader__':
<_frozen_importlib_external.SourceFileLoader object at 0x7fb2b1ccb7c0>,
'__spec__': None, '
__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>,
'__file__': 'main.py',
'__cached__': None,
'seasons_to_vals': {'Spring': 1, 'Summer': 2, 'Fall': 3, 'Winter': 4},
'Spring': 1, 'Summer': 2, 'Fall': 3, 'Winter': 4}
There are a lot of mappings like “__name__” and “__doc__” that you don’t need to worry about. But note carefully the difference between the locals table before and after our statement updating the table (in the line “locals().update(seasons_to_vals)”). After the updating, there are new mappings created. There is a mapping first for the dictionary “seasons_to_vals”. Then there are four mappings, one for each of the variables who are keys of the dictionary.
Now let us see if this worked by trying to print these variables:
print(Spring)
print(Summer)
print(Fall)
print(Winter)
Note that these are interpreted as variable names, not strings (in which case we would have enclosed them in quotes). The output is:
1
2
3
4
as desired.
The same code above will work if we had used globals() instead of locals() because the dictionary and variables are in the global scope:
print("BEFORE:")
print(globals())
seasons_to_vals = {}
seasons_to_vals['Spring'] = 1
seasons_to_vals['Summer'] = 2
seasons_to_vals['Fall'] = 3
seasons_to_vals['Winter'] = 4
print("AFTER:")
globals().update(seasons_to_vals)
print(globals())
print(Spring)
print(Summer)
print(Fall)
print(Winter)
The output will be (something like):
BEFORE:
{'__name__': '__main__',
'__doc__': None,
'__package__': None,
'__loader__':
<_frozen_importlib_external.SourceFileLoader object at 0x7f0a02aa77c0>,
'__spec__': None,
'__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>,
'__file__': 'main.py',
'__cached__': None}
AFTER:
{'__name__': '__main__',
'__doc__': None,
'__package__': None,
'__loader__':
<_frozen_importlib_external.SourceFileLoader object at 0x7f0a02aa77c0>,
'__spec__': None,
'__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>,
'__file__': 'main.py',
'__cached__': None,
'seasons_to_vals': {'Spring': 1, 'Summer': 2, 'Fall': 3, 'Winter': 4},
'Spring': 1, 'Summer': 2, 'Fall': 3, 'Winter': 4}
1
2
3
4
Thus we have seen two different ways to unpack a dictionary into variables. We can use either the exec() function to make assignments by iterating over the dictionary entries, or the locals().update() method or globals().update() methods to directly map the dictionary to modify the symbol table. Which approach is your favorite?
Now that you have figured out how to convert a Python dictionary into variables, learn how to do the reverse, i.e., how to pack multiple variables into a dictionary. Also learn how to save a dictionary in JSON format. Also learn how to shuffle a Python dictionary (and what that means).
Interested in more things Python? Checkout our post on Python queues. Also see our blogpost on Python's enumerate() capability. Also if you like Python+math content, see our blogpost on Magic Squares. Finally, master the Python print function!
Want to learn Python with us? Sign up for 1:1 or small group classes.