Comp 112
Lecture 10
Tuples and Dictionaries2018.04.03
Recall that a homogeneous list has fixed type but variable length:
In contrast, a tuple has fixed size but each field can have a different type:
Tuples are one way to collect related data into one object. (We’ll meet other ways soon.)
A tuple is written like a list, but without the brackets.
Often parentheses are needed to mark the start/end of a tuple.
Unlike lists, tuples are immutable.
In our signatures for tuples, we’ll include the signature for each of its fields.
Like lists, tuples support indexing:
…and also slicing: a slice of a tuple is another tuple:
Because they are immutable, tuples don’t support index assignment or slice assignment.
Functions may take any number of arguments, but must return exactly one result.
With tuples we can simulate returning multiple results:
By forming tuples of variables, we can perform multiple assignments at once.
This is useful for deconstructing a tuple into its parts:
We can use tuple assignment to swap the values of variables:
Sometimes we want to iterate over a list without controlling the order, but we still want access to the indices:
def indices (needle , haystack) : # from homework 5
"""
signature : any a . a , list (a) -> list (int)
returns the list of matching indices
"""
acc = []
i = 0
while i < len (haystack) :
if needle == haystack [i] :
acc.append (i)
i += 1
return acc
There is a built-in function called enumerate
with signature any a . iterator a -> iterator (tuple (int , a))
that packages up each list entry with its index:
Letting us write:
A homogeneous list of tuples can act as a table or spreadsheet:
We can use Python to write spreadsheet functions:
One way to think of a list:
is as a look-up table:
index | value | |
---|---|---|
0 | ⟼ | "John" |
1 | ⟼ | "Paul" |
2 | ⟼ | "George" |
3 | ⟼ | "Ringo" |
From this perspective, the table’s look-up indices are the numbers from 0
to len(xs)-1
.
But there is no reason why a table’s look-up indices need to be these particular numbers.
index | value | |
---|---|---|
0 | ⟼ | "N/A" |
1 | ⟼ | "N/A" |
⋮ | ||
1895 | ⟼ | "N/A" |
1896 | ⟼ | "Thomas Burke" |
1897 | ⟼ | "N/A" |
1898 | ⟼ | "N/A" |
1899 | ⟼ | "N/A" |
1900 | ⟼ | "Frank Jarvis" |
1901 | ⟼ | "N/A" |
⋮ | ||
2015 | ⟼ | "N/A" |
2016 | ⟼ | "Usain Bolt" |
…or even numbers at all.
Python has a look-up table type where the indices can be values of any immutable type. It is called a dictionary.
An index of a dictionary is called a key.
The item in a dictionary indexed by a key is called its value.
For lookup, dictionaries support indexing (“_[_]
”), just like lists.
For assignment, dictionaries support index assignment, just like lists.
For deleting an entry from a dictionary, there is a del
operator: “del <dictionary> [<key>]
”.
The “dict
” function creates a new empty dictionary.
olympic_mens_100 = dict () # signature: dict (int -> str)
olympic_mens_100 [1896] = 'Thomas Burke' # ...
olympic_mens_100 [1988] = 'Ben Johnson'
del olympic_mens_100 [1988] # revoked due to doping
olympic_mens_100 [1988] = 'Carl Lewis' # ...
olympic_mens_100 [2008] = 'Usain Bolt'
olympic_mens_100 [2012] = 'Usain Bolt'
olympic_mens_100 [2016] = 'Usain Bolt'
Our signatures for dictionaries include the signatures for the keys and values.
Similar to the way we can write lists using bracket notation:
We can write dictionaries using brace notation:
Each key-value pair is written:
The key-value pairs are separated by commas, just like list elements.
If a key is repeated, its last value will overwrite any earlier ones.
The dictionary keys
method returns the keys of a dictionary:
om100_keys = olympic_mens_100.keys ()
The dictionary values
method return the values (with repetitions) stored in a dictionary:
The dictionary items
method returns the key-value pairs of a dictionary as tuples:
The objects returned by these methods are list-like iterators.
If you need an actual list then coerce them with the list
function:
om100_key_list = list (olympic_mens_100.keys ())
We can iterate over the object returned by the dictionary keys
method:
As a shorthand, we can iterate over the dictionary object itself:
Or we can iterate over the key-value pairs returned by the dictionary items
method:
Recall that there is a function called sorted
that returns a sorted (according to “_<=_
”) version of a list (or iterator):
To sort our olympic records chronologically:
or:
The “_in_
” and “_not in_
” operators are overloaded to work with dictionaries.
They test for the presence of keys (but not values).
def letter_counts (text) :
# signature: str -> dictionary (str -> int)
counts = dict () # initialize the dictionary
for character in text.lower () : # count the letter occurrences
if str.isalpha (character) :
if character not in counts :
counts [character] = 0
counts [character] += 1
return counts
def print_dict (dictionary) :
# signature: any a . dict (str -> a) -> NoneType
# prints sorted contents of the dictionary
for (key , val) in sorted (dictionary.items ()) :
print (key + ": " + str (val))
two_cities = "It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, \
it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, \
it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us..."
Reading:
Come to lab on Thursday.
Complete homework 10.