This repository has been archived by the owner on Oct 9, 2024. It is now read-only.
generated from UniExeterRSE/UoE-workshop-template
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add section on dictionaries, and additional exercises.
- Loading branch information
1 parent
104e686
commit b77c1c1
Showing
3 changed files
with
294 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
--- | ||
layout: page | ||
title: Dictionaries | ||
order: 5 | ||
session: 1 | ||
length: 15 | ||
toc: true | ||
--- | ||
|
||
## Learning Objectives | ||
|
||
At the end of this lesson you will be able to: | ||
|
||
- Identify and explain what a dictionary is | ||
- Explain what makes a dictionary different to a list | ||
- Understand the `key`: `value` relationship | ||
- Create a dictionary containing simple values | ||
- Update values in a dictionary | ||
|
||
## Key points | ||
|
||
- A dictionary stores key-value pairs. | ||
- Dictionaries are unordered. | ||
- Dictionaries are immutable. | ||
|
||
## Introduction | ||
|
||
Lists and arrays are useful, but don’t cover every use case. One of Python’s best features is its “dictionary” data structure. Whereas a list or array is simply a collection of elements, a dictionary supports key-value storage of data. Put into plain english, it lets you store and retrieve data values by name. | ||
|
||
## Create a dictionary | ||
|
||
Let’s create and use a simple dictionary of scientist's birth years to illustrate this: | ||
|
||
~~~ | ||
birth_years = {'Newton': 1642, 'Darwin': 1809, 'Einstein': 1979, 'Nobel': 1833} | ||
print(birth_years) | ||
~~~ | ||
{: .language-python} | ||
|
||
~~~ | ||
{'Newton': 1642, 'Darwin': 1809, 'Einstein': 1979, 'Nobel': 1833} | ||
~~~ | ||
{: .output} | ||
|
||
Here, 'Newton', 'Darwin', 'Einstein' and 'Nobel' are keys, and the years are values. Keys and values form a pairwise mapping, allowing the retrieval of a value via the value's key. | ||
|
||
We can retrieve a value from a dictionary by entering the correct key for this value. We do this using the following syntax: | ||
|
||
~~~ | ||
value_we_want = dictionary['key_of_value_we_want'] | ||
~~~ | ||
{: .language-python} | ||
|
||
This is similar to accessing a value stored in a list. However, the key does not have to be an integer. | ||
|
||
## Retrieve a value | ||
|
||
> Retrieve the birth year for Isaac Newton from the dictionary of birth years. | ||
> | ||
> > ## Solution | ||
> > ~~~ | ||
> > birth_years = {'Newton': 1642, 'Darwin': 1809, 'Einstein': 1979, 'Nobel': 1833} | ||
> > birth_years['Newton'] | ||
> > ~~~ | ||
> > {: .language-python} | ||
> > ~~~ | ||
> > 1642 | ||
> > ~~~ | ||
> > {: .output} | ||
> {: .solution} | ||
{: .challenge} | ||
## Altering a dictionary | ||
Similar to lists, dictionaries are mutable. We can add a value to a dictionary, using a key: | ||
~~~ | ||
birth_years = {'Newton': 1642, 'Darwin': 1809, 'Einstein': 1979, 'Nobel': 1833} | ||
birth_years['Turing'] = 1612 | ||
print(birth_years) | ||
~~~ | ||
{: .language-python} | ||
~~~ | ||
{'Newton': 1642, 'Darwin': 1809, 'Einstein': 1979, 'Nobel': 1833, 'Turing': 1612} | ||
~~~ | ||
{: .output} | ||
Oops, we made a mistake there. Turing was actually born in 1912. We can update a value using a key. | ||
Turing's birthdate above is actual incorrect. Values may be overwritten by re-assignment: | ||
~~~ | ||
birth_years = {'Newton': 1642, 'Darwin': 1809, 'Einstein': 1979, 'Nobel': 1833, 'Turing': 1612} | ||
birth_years['Turing'] = 1912 | ||
print(birth_years) | ||
~~~ | ||
{: .language-python} | ||
~~~ | ||
{'Newton': 1642, 'Darwin': 1809, 'Einstein': 1979, 'Nobel': 1833, 'Turing': 1912} | ||
~~~ | ||
{: .output} | ||
## Add your own scientists to a dictionary | ||
> Add two more scientist's birth years to our dictionary of birth years. | ||
> | ||
> > ## Solution | ||
> > ~~~ | ||
> > birth_years = {'Newton': 1642, 'Darwin': 1809, 'Einstein': 1979, 'Nobel': 1833, 'Turing': 1612} | ||
> > birth_years['Curie'] = 1867 | ||
> > birth_years['Franklin'] = 1920 | ||
> > print(birth_years) | ||
> > ~~~ | ||
> > {: .language-python} | ||
> > ~~~ | ||
> > {'Newton': 1642, 'Darwin': 1809, 'Einstein': 1979, 'Nobel': 1833, 'Turing': 1612, 'Curie': 1867, 'Franklin': 1920} | ||
> > ~~~ | ||
> > {: .output} | ||
> {: .solution} | ||
{: .challenge} | ||
## Retrieve all keys and values | ||
Dictionaries contain a number of in-built methods that allow you to easily access the data contained within. These methods are automatically attached to every dictionary. | ||
~~~ | ||
birth_years = {'Newton': 1642, 'Darwin': 1809, 'Einstein': 1979, 'Nobel': 1833, 'Turing': 1612, 'Curie': 1867, 'Franklin': 1920} | ||
birth_years.keys() | ||
~~~ | ||
{: .language-python} | ||
~~~ | ||
dict_keys(['Newton', 'Darwin', 'Einstein', 'Nobel', 'Turing', 'Curie', 'Franklin']) | ||
~~~ | ||
{: .output} | ||
Similarly for values: | ||
~~~ | ||
birth_years.values() | ||
~~~ | ||
{: .language-python} | ||
~~~ | ||
dict_values([1642, 1809, 1979, 1833, 1612, 1867, 1920]) | ||
~~~ | ||
{: .output} | ||
We can convert these to lists: | ||
~~~ | ||
list(birth_years.values()) | ||
~~~ | ||
{: .language-python} | ||
~~~ | ||
[1642, 1809, 1979, 1833, 1612, 1867, 1920] | ||
~~~ | ||
{: .output} | ||
And finally, retrieve the key, value pairs together, forming a list of tuples: | ||
~~~ | ||
list(birth_years.items()) | ||
~~~ | ||
{: .language-python} | ||
~~~ | ||
[('Newton', 1642), ('Darwin', 1809), ('Einstein', 1979), ('Nobel', 1833), ('Turing', 1612), ('Curie', 1867), ('Franklin', 1920)] | ||
~~~ | ||
{: .output} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
--- | ||
layout: page | ||
title: Additional exercises | ||
order: 8 | ||
session: 1 | ||
length: 20 | ||
toc: true | ||
--- | ||
|
||
## Swapping the contents of variables | ||
|
||
> Explain what the overall effect of this code is: | ||
> | ||
> ~~~ | ||
> left = 'L' | ||
> right = 'R' | ||
> | ||
> temp = left | ||
> left = right | ||
> right = temp | ||
> ~~~ | ||
> {: .language-python} | ||
> | ||
> Compare it to: | ||
> | ||
> ~~~ | ||
> left, right = right, left | ||
> ~~~ | ||
> {: .language-python} | ||
> | ||
> Do they always do the same thing? | ||
> Which do you find easier to read? | ||
> | ||
> > ## Solution | ||
> > Both examples exchange the values of `left` and `right`: | ||
> > | ||
> > ~~~ | ||
> > print(left, right) | ||
> > ~~~ | ||
> > {: .language-python} | ||
> > | ||
> > ~~~ | ||
> > R L | ||
> > ~~~ | ||
> > {: .output} | ||
> > | ||
> > In the first case we used a temporary variable `temp` to keep the value of `left` before we | ||
> > overwrite it with the value of `right`. In the second case, `right` and `left` are packed into a | ||
> > [tuple]({{ page.root }}/reference.html#tuple) | ||
> > and then unpacked into `left` and `right`. | ||
> {: .solution} | ||
{: .challenge} | ||
## Turn a String into a List | ||
> Use a for-loop to convert the string "hello" into a list of letters: | ||
> | ||
> ~~~ | ||
> ["h", "e", "l", "l", "o"] | ||
> ~~~ | ||
> {: .language-python} | ||
> | ||
> Hint: You can create an empty list like this: | ||
> | ||
> ~~~ | ||
> my_list = [] | ||
> ~~~ | ||
> {: .language-python} | ||
> | ||
> > ## Solution | ||
> > ~~~ | ||
> > my_list = [] | ||
> > for char in "hello": | ||
> > my_list.append(char) | ||
> > print(my_list) | ||
> > ~~~ | ||
> > {: .language-python} | ||
> {: .solution} | ||
{: .challenge} | ||
## Reverse a String | ||
> Knowing that two strings can be concatenated using the `+` operator, | ||
> write a loop that takes a string | ||
> and produces a new string with the characters in reverse order, | ||
> so `'Newton'` becomes `'notweN'`. | ||
> | ||
> > ## Solution | ||
> > ~~~ | ||
> > newstring = '' | ||
> > oldstring = 'Newton' | ||
> > for char in oldstring: | ||
> > newstring = char + newstring | ||
> > print(newstring) | ||
> > ~~~ | ||
> > {: .language-python} | ||
> {: .solution} | ||
{: .challenge} | ||
## Fixing and Testing | ||
> Fix `range_overlap`. Re-run `test_range_overlap` after each change you make. | ||
> | ||
> > ## Solution | ||
> > ~~~ | ||
> > def range_overlap(ranges): | ||
> > '''Return common overlap among a set of [left, right] ranges.''' | ||
> > if not ranges: | ||
> > # ranges is None or an empty list | ||
> > return None | ||
> > max_left, min_right = ranges[0] | ||
> > for (left, right) in ranges[1:]: | ||
> > max_left = max(max_left, left) | ||
> > min_right = min(min_right, right) | ||
> > if max_left >= min_right: # no overlap | ||
> > return None | ||
> > return (max_left, min_right) | ||
> > ~~~ | ||
> > {: .language-python} | ||
> {: .solution} | ||
{: .challenge} |