Learn Python Series (#7) - Handling Dictionaries
<p dir="auto"><img src="https://images.hive.blog/768x0/https://res.cloudinary.com/hpiynhbhq/image/upload/v1520771501/jyhoteomp3nxmstkpl0t.png" alt="python_logo.png" srcset="https://images.hive.blog/768x0/https://res.cloudinary.com/hpiynhbhq/image/upload/v1520771501/jyhoteomp3nxmstkpl0t.png 1x, https://images.hive.blog/1536x0/https://res.cloudinary.com/hpiynhbhq/image/upload/v1520771501/jyhoteomp3nxmstkpl0t.png 2x" />
<h4>What Will I Learn?
<ul>
<li>You will learn how to create and copy dictionaries using various techniques,
<li>how to get (access) and set (add or modify) dictionary items / item values,
<li>how to remove them,
<li>you will learn about dictionary view objects and methods, and
<li>about iterating over dictionaries.
<h4>Requirements
<ul>
<li>A working modern computer running macOS, Windows or Ubuntu
<li>An installed Python 3(.6) distribution, such as (for example) the Anaconda Distribution
<li>The ambition to learn Python programming
<h4>Difficulty
<p dir="auto">Intermediate
<h4>Curriculum (of the <code>Learn Python Series):
<ul>
<li><a href="https://utopian.io/utopian-io/@scipio/learn-python-series-intro" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Learn Python Series - Intro
<li><a href="https://utopian.io/utopian-io/@scipio/learn-python-series-2-handling-strings-part-1" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Learn Python Series (#2) - Handling Strings Part 1
<li><a href="https://utopian.io/utopian-io/@scipio/learn-python-series-3-handling-strings-part-2" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Learn Python Series (#3) - Handling Strings Part 2
<li><a href="https://utopian.io/utopian-io/@scipio/learn-python-series-4-round-up-1" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Learn Python Series (#4) - Round-Up #1
<li><a href="https://utopian.io/utopian-io/@scipio/learn-python-series-5-handling-lists-part-1" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Learn Python Series (#5) - Handling Lists Part 1
<li><a href="https://utopian.io/utopian-io/@scipio/learn-python-series-6-handling-lists-part-2" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Learn Python Series (#6) - Handling Lists Part 2
<h1>Learn Python Series (#7) - Handling Dictionaries
<p dir="auto">In this <code>Learn Python Series episode we will be reviewing the built-in Python data type <strong>dictionary.
<p dir="auto">In this episode you will learn how to create and copy dictionaries using various techniques, how to get (access) and set (add or modify) dictionary items / item values, how to remove them, you will learn about dictionary view objects and methods, and about iterating over dictionaries.
<h1>What is a dictionary actually?
<p dir="auto">A dictionary is a <strong>mapping object (currently the only standard one), meaning that it "maps" hashable mutable values to immutable keys, making the mappings themselves mutable.
<p dir="auto">A dictionary stores data as an <strong>unordered collection of <strong>{<code>key:<code>value} pairs. (Most) other data types just have an element value. A dictionary <code>value can be of any data type (meaning we can easily create <strong>nested dictionaries because the value can be another dictionary), but a <code>key must be an immutable data type (like a tuple, a string, or a number).
<h1>Creating and copying dictionaries
<h3>Creating using <code>{} versus <code>dict()
<p dir="auto">You can create a new dictionary either by using <strong>curly braces <code>{}, or by using the built-in <code>dict() function. It can be empty while initiating it, or filled with some <code>key:<code>value pairs right away. Like so:
<pre><code># Create an empty dictionary using curly braces `{}`
dict_1 = {}
print(dict_1)
# {}
# Create an empty dictionary using `dict()`
dict_2 = dict()
print(dict_2)
# {}
# Create a dictionary with mixed keys
# (strings and integers)
dict_3 = {'name': 'scipio',
'roles': ['advisor', 'moderator', 'contributor'],
1: 'banana',
2: 'dog' }
print(dict_3)
'''
{'name': 'scipio',
'roles': ['advisor', 'moderator', 'contributor'],
1: 'banana',
2: 'dog'}
'''
<pre><code>{}
{}
{'name': 'scipio', 'roles': ['advisor', 'moderator', 'contributor'], 1: 'banana', 2: 'dog'}
<h3>Creating using <code>dict.fromkeys(sequence[, value])
<p dir="auto">The <code>dict.fromkeys() method can be used to create a dictionary by using the values contained in a sequence (such as a string or a list). Optionally a <code>value argument may be set, via which every dictionary will be set to that same corresponding value.
<p dir="auto">Please observe the following examples:
<pre><code># Create dictionary from list
my_list = ['a', 'b', 'c']
my_dict = dict.fromkeys(my_list)
print(my_dict)
# {'a': None, 'b': None, 'c': None}
# Create dictionary from string
my_string = 'scipio'
my_dict = {}.fromkeys(my_string)
print(my_dict)
# {'s': None, 'c': None, 'i': None, 'p': None, 'o': None}
# .....
# Notice there are two 'i' characters
# in the string "scipio",
# and only one `i` key in the dictionary
# Pass a default `value` argument
my_keys = 'abcde'
my_val = 100
my_dict = {}.fromkeys(my_keys, my_val)
print(my_dict)
# {'a': 100, 'b': 100, 'c': 100, 'd': 100, 'e': 100}
<pre><code>{'a': None, 'b': None, 'c': None}
{'s': None, 'c': None, 'i': None, 'p': None, 'o': None}
{'a': 100, 'b': 100, 'c': 100, 'd': 100, 'e': 100}
<h3>Copying using <code>= versus <code>dict.copy()
<p dir="auto">As is the case with lists, it is possible to copy dictionaries using the <code>= operator. But if you change one copy (for example using <code>dict.update() explained below), you also change the other. This is because the <code>= operator only creates a <strong>reference to the original dictionary. For example:
<pre><code>a = {'one': 1, 'two': 2, 'three': 3}
b = a
b.update({'two': 9})
print(a, b)
# {'one': 1, 'two': 9, 'three': 3} {'one': 1, 'two': 9, 'three': 3}
<pre><code>{'one': 1, 'two': 9, 'three': 3} {'one': 1, 'two': 9, 'three': 3}
<p dir="auto">To avoid this behavior, use <code>dict.copy() to create a so-called <strong>shallow copy, where a <strong>new dictionary is created. Like so:
<pre><code>a = {'one': 1, 'two': 2, 'three': 3}
b = a.copy()
b.update({'two': 9})
print(a,b)
# `a` now stays unmodified
# {'one': 1, 'two': 2, 'three': 3} {'one': 1, 'two': 9, 'three': 3}
<pre><code>{'one': 1, 'two': 2, 'three': 3} {'one': 1, 'two': 9, 'three': 3}
<h1>Getting & setting dictionary items
<h3>Getting values using <code>[] versus <code>dict.get()
<p dir="auto">Up until now, using strings, tuples and lists, we were accessing element values by using their index / position in the data container. But because dictionaries have no order, you can't access the dictionary items via their index. The most common way to access individual dictionary items is by using their <code>key, either with a squared bracket <code>[] notation or by using the <code>get() method.
<p dir="auto">Please note, that if the key was not found inside the dictionary, <code>[] raises a KeyError, while <code>get() will return <code>None.
<p dir="auto">For example:
<pre><code>dict_3 = {'name': 'scipio',
'roles': ['advisor', 'moderator', 'contributor'],
1: 'banana',
2: 'dog' }
# Access elements using `[]`
name = dict_3['name']
print(name)
# scipio
# Access elements using `get()`
roles = dict_3.get('roles')
print(roles)
# ['advisor', 'moderator', 'contributor']
<pre><code>scipio
['advisor', 'moderator', 'contributor']
<h3>Getting & setting using <code>dict.setdefault(key[, default_value])
<p dir="auto">The <code>dict.setdefault() method <strong>gets item values by key, similar to <code>dict.get(), but - in case the key is not present in the dictionary - it <strong>sets <code>dict[key]. In case of a set, when no default value is passed as an argument, then <code>None will be set, otherwise the default value will be set.
<p dir="auto">Like so:
<pre><code>account = {'name': 'scipio', 'age_days': 133}
# Get value with key present, no default
name = account.setdefault('name')
print(name, account)
# scipio {'name': 'scipio', 'age_days': 133}
# Get value with key present, default
age = account.setdefault('age_days', 365)
print(age, account)
# 133 {'name': 'scipio', 'age_days': 133}
# PS: because the key is present, nothing is set / modified
# Get value with key absent, no default:
# `None` value is set.
sbd = account.setdefault('sbd')
print(sbd, account)
# None {'name': 'scipio', 'age_days': 133, 'sbd': None}
# Get value with key absent, no default:
# `Default argument` value is set.
steempower = account.setdefault('steempower', 999999)
print(steempower, account)
# 999999 {'name': 'scipio', 'age_days': 133, 'sbd': None, 'steempower': 999999}
<pre><code>scipio {'name': 'scipio', 'age_days': 133}
133 {'name': 'scipio', 'age_days': 133}
None {'name': 'scipio', 'age_days': 133, 'sbd': None}
999999 {'name': 'scipio', 'age_days': 133, 'sbd': None, 'steempower': 999999}
<h1>Updating (modifying) and adding dictionairy items
<h3>Using the <code>= operator
<p dir="auto">Because dictionaries are mutable, we can simply add and modify its using the assignment <code>= operator. The syntax is: <code>dict[key] = value. If the key isn't there, it gets added, and if it is, it gets modified. For example:
<pre><code>my_dict = {'a': 100, 'b': 50}
print(my_dict)
# {'a': 100, 'b': 50}
# adding an item
my_dict['c'] = 100
print(my_dict)
# {'a': 100, 'b': 50, 'c': 100}
# modifying an item
my_dict['a'] = 200
print(my_dict)
# {'a': 100, 'b': 50, 'c': 100}
<pre><code>{'a': 100, 'b': 50}
{'a': 100, 'b': 50, 'c': 100}
{'a': 200, 'b': 50, 'c': 100}
<h3>Using the <code>dict.update() method
<p dir="auto">The <code>update() method updates existing items or adds then when absent. As the <code>update() argument a dictionary, a list of 2-tuples, or keyword arguments are accepted. This works as follows:
<pre><code>test = {'a': 1, 'b': 2}
# update with dictionary
test.update({'a': 100, 'b': 200, 'c': 300})
print(test)
# {'a': 100, 'b': 200, 'c': 300}
# update with a list of 2-tuples
test.update([('d', 40),('a', 10),('c', 10)])
print(test)
# {'a': 10, 'b': 200, 'c': 10, 'd': 40}
# update with keyword arguments
test.update(a=50, b=100, c=150, d=200)
print(test)
<pre><code>{'a': 100, 'b': 200, 'c': 300}
{'a': 10, 'b': 200, 'c': 10, 'd': 40}
{'a': 50, 'b': 100, 'c': 150, 'd': 200}
<h1>Removing dictionary items
<p dir="auto">Python has various "dictionary-only" methods and built-in functions for removing items from a dictionary, or the entire dictionary itself. We will hereby discuss (most of) them.
<h3>Using the <code>dict.pop(key[, default]) method
<p dir="auto">The <code>pop() method looks if a given <code>key is in the dictionary, and if so, it both removes it and returns its value. When the <code>key is not in the dictionary, either a KeyError is raised or, if set, the <code>default value is returned. Please observe the following examples:
<pre><code>my_dict1 = {'one': 1, 'two': 2, 'three': 3}
# Remove and return `'three'`
res = my_dict1.pop('three')
print(res, my_dict1)
# 3 {'one': 1, 'two': 2}
<pre><code>3 {'one': 1, 'two': 2}
<pre><code># Remove and return `'four'`, which is absent,
# so in turn return the default `9` value,
# and not a KeyError
my_dict2 = {'one': 1, 'two': 2, 'three': 3, 'five': 5}
res = my_dict2.pop('four', 9)
print(res, my_dict2)
# 9 {'one': 1, 'two': 2, 'three': 3, 'five': 5}
<pre><code>9 {'one': 1, 'two': 2, 'three': 3, 'five': 5}
<h3>Using the <code>dict.popitem() method
<p dir="auto">The <code>popitem() method doesn't accept any argument, and removes and returns an <strong>arbitrary item from the dictionary. Like is the case with <code>dict.pop(), in case <code>popitem() is called at an empty dictionary, a KeyError is raised.
<p dir="auto">Question: Why is <code>popitem() useful, if you're unable to determine which key will be removed and returned?<br />
Answer: <code>popitem() can be be used to destructively iterate, using a loop, over a dictionary.
<p dir="auto">Please regard the following examples:
<pre><code>test1 = {'one': 1, 'two': 2, 'three': 3}
# Remove and return one existing item
result = test1.popitem()
print(result)
print(test1)
# ('three', 3)
# {'one': 1, 'two': 2}
<pre><code>('three', 3)
{'one': 1, 'two': 2}
<pre><code>test2 = {'one': 1, 'two': 2, 'three': 3}
# Create a `destruct_dict()` function
def destruct_dict(dict):
while len(dict) > 0:
print(dict.popitem(), dict)
else:
print('Done!')
# Call `destruct_dict()`
destruct_dict(test2)
# ('three', 3) {'one': 1, 'two': 2}
# ('two', 2) {'one': 1}
# ('one', 1) {}
# Done!
<pre><code>('three', 3) {'one': 1, 'two': 2}
('two', 2) {'one': 1}
('one', 1) {}
Done!
<p dir="auto"><strong>PS: did you notice that I now used a <code>while .. else clause? ;-)
<h3>Using the <code>dict.clear() method
<p dir="auto">Like lists, dictionaries also have a <code>clear() method, which removes all items contained in a dictionary.
<pre><code>test3 = {'one': 1, 'two': 2, 'three': 3}
test3.clear()
print(test3)
# {}
<pre><code>{}
<h3>Using the <code>del statement
<p dir="auto">As is the case with lists, dictionaries can also make use of the del statement to remove items from a dictionary or delete the entire dictionary. For example:
<pre><code>test4 = {'one': 1, 'two': 2, 'three': 3}
# remove one item
del test4['three']
print(test4)
# {'one': 1, 'two': 2}
# remove the entire dictionary
del test4
<pre><code>{'one': 1, 'two': 2}
<h1>Dictionary view objects
<p dir="auto">A dictionary can use the methods <code>dict.keys(), <code>dict.values(), and <code>dict.items(). The objects that are returned are so-called <strong>view objects and they are iterable.
<p dir="auto">When iterating (using a loop) over dictionary keys and values, the order in which that happens is <strong>arbitrary, but non-random, dependent on when what was added, deleted and modified on the dictionary, and the order varies per Python distribution.
<p dir="auto">However, when iterating over dictionary views, the keys and values are iterated over in the same order, which allows for zipping <code>(value, key) and <code>(key, value) pairs using <code>zip().
<p dir="auto">For example:
<pre><code># Iterate over the dict numerical values
# and sum them.
a = {'one': 1, 'two': 2, 'three': 3}
values = a.values()
total = 0
for val in values:
total += val
print(total)
# 6
# Iterating over keys and values is done
# in the same order for keys and values
b = {'dogs': 10, 'cats': 15, 'cows': 20}
keys = b.keys()
values = b.values()
print(list(keys))
print(list(values))
# ['dogs', 'cats', 'cows']
# [10, 15, 20]
# .....
# And because the keys and values are
# in the same order, that allows for
# zipping the key/value views as pairs
pairs = list(zip(keys, values))
print(pairs)
# [('dogs', 10), ('cats', 15), ('cows', 20)]
# ...
# Same thing using `dict.items()`
c = {'account': 'utopian-io', 'rep': 66.1, 'age_days': 159}
items = c.items()
print(list(items))
<pre><code>6
['dogs', 'cats', 'cows']
[10, 15, 20]
[('dogs', 10), ('cats', 15), ('cows', 20)]
[('account', 'utopian-io'), ('rep', 66.1), ('age_days', 159)]
<h1>Handling nested dictionaries
<p dir="auto">Up until now, we've been discussing "flat" dictionary structures. But in case a dictionary <code>value is a <strong>dictionary itself, ergo, when a <code>value itself consists of one or more <code>key:<code>value <strong>pairs, then, in that case, a dictionary is contained within another dictionary, which is called a <strong>nested dictionary.
<p dir="auto">For example:
<pre><code># `dict_nested` holds 2 dicts:
# `dict1` and `dict2`
dict_nested = {
'dict1': {'key': 1},
'dict2': {'key': 5}
}
print(dict_nested)
# {'dict1': {'key': 1}, 'dict2': {'key': 5}}
<pre><code>{'dict1': {'key': 1}, 'dict2': {'key': 5}}
<h3>Getting and setting nested items
<p dir="auto">All the previously discussed dictionary methods and techniques apply to nested dictionaries as well, for example using the squared bracket <code>[] notation, repeatedly.
<pre><code>countries = {
'USA': {'capital': 'Washington, D.C.', 'main_language': 'English'},
'Germany': {'capital': 'Berlin', 'main_language': 'German'},
'France': {'capital': 'Paris', 'main_language': 'French'},
'The Netherlands': {'capital': 'Amsterdam', 'main_language': 'Dutch'}
}
# get individual values
print(countries['USA']['main_language'])
print(countries['The Netherlands']['capital'])
<pre><code>English
Amsterdam
<pre><code>countries = {
'USA': {'capital': 'Washington, D.C.', 'main_language': 'English'},
'Germany': {'capital': 'Berlin', 'main_language': 'German'},
'France': {'capital': 'Paris', 'main_language': 'French'},
'The Netherlands': {'capital': 'Amsterdam', 'main_language': 'Dutch'}
}
# iterating over the outer dict keys
for country in countries:
print(country)
<pre><code>USA
Germany
France
The Netherlands
<pre><code>countries = {
'USA': {'capital': 'Washington, D.C.', 'main_language': 'English'},
'Germany': {'capital': 'Berlin', 'main_language': 'German'},
'France': {'capital': 'Paris', 'main_language': 'French'},
'The Netherlands': {'capital': 'Amsterdam', 'main_language': 'Dutch'}
}
# iterating over outer items and inner keys
for country, data in countries.items():
print('Country:',country)
print('------------------')
for key in data:
print(key + ':\t' + data[key])
print('\n')
<pre><code>Country: USA
------------------
capital: Washington, D.C.
main_language: English
Country: Germany
------------------
capital: Berlin
main_language: German
Country: France
------------------
capital: Paris
main_language: French
Country: The Netherlands
------------------
capital: Amsterdam
main_language: Dutch
<h1>What did we learn, hopefully?
<p dir="auto">That dictionaries are a very interesting and useful data type, what dictionaries are and how to use them. In the next few episodes we will continue discussing some more built-in Python data types. See you there!
<h3>Thank you for your time!
<p dir="auto"><br /><hr /><em>Posted on <a href="https://utopian.io/utopian-io/@scipio/learn-python-series-7-handling-dictionaries" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Utopian.io - Rewarding Open Source Contributors<hr /><p>
You are very intelligent @scipio
Thanks for your helpful blog @scipio
Indeed. You must be very intelligent @scipio!
Thank you for the contribution. It has been approved.
You can contact us on Discord.
[utopian-moderator]
This post has been upvoted and picked by Daily Picked #3! Thank you for the cool and quality content. Keep going!
Don’t forget I’m not a robot. I explore, read, upvote and share manually :)
Hey @scipio I am @utopian-io. I have just upvoted you!
Achievements
Community-Driven Witness!
I am the first and only Steem Community-Driven Witness. Participate on Discord. Lets GROW TOGETHER!
Up-vote this comment to grow my power and help Open Source contributions like this one. Want to chat? Join me on Discord https://discord.gg/Pc8HG9x