click to view as a presentation
Students will be able to:
-
Use lists, tuples & dictionaries as containers for data
-
Use list comprehensions to create lists
-
Create subsets of a sequence using the slice operator
- To test some of the examples and complete the exercises, please open a Python repl.it
-
As you know by now, applications frequently need to maintain collections of data within a container data type.
-
What did we use in JS to hold collections of data?
-
In this lesson, we're going to review the following Python built-in types commonly used as containers:
- dictionaries
- lists
- tuples
-
Dictionaries are to Python as objects are to JS.
-
A dictionary provides a container for
key: value
pairs. We can refer tokey: value
pairs as items. -
Dictionaries have a class (type) of
dict
.
-
Like objects in JS, a dictionary is created with a set of curly braces:
student = { 'name': 'Fred', 'course': 'SEI', 'current_week': 7 }
-
Unlike in JS, strings used as keys must be quoted.
-
If not quoted, Python expects the identifier to be a variable holding what you want to use as the key. This is similar to how computed properties work in JS.
Dictionaries have the following features:
-
They are unordered (just like JS objects)
-
They are mutable:
- The values assigned to a key can be changed
- Additional items can be added
- Existing items can be deleted
-
Any immutable type can be used as a key, including numbers and tuples (which we'll cover in a bit).
-
We use square brackets to get and set an item's value:
name = student['name'] print(name) > Fred student['name'] = 'Tina' print(student['name']) > Tina
-
Unlike JS, you cannot access items in a Python dictionary using dot notation (dots are used to invoke methods on the dictionary).
-
Unlike JS which returns
undefined
when accessing a property that does not exist, a dictionary will raise aKeyError
. -
One option to avoid this error is to use the
get
method:birthdate = student['birthdate'] > KeyError: 'birthdate' print( student.get('birthdate') ) > None # Provide a default value if key not in dictionary print( student.get('birthdate', '07-04-1776') ) > 07-04-1776
-
Another way to avoid the
KeyError
is to use thein
operator to check if the dictionary includes a key:if 'course' in student: print( f"{student['name']} is enrolled in {student['course']}") else: print( f"{student['name']} is not enrolled in a course")
-
Simply assigning to a key that does not exist will create a new item in the dictionary:
student['age'] = 21
-
The
del
statement is used to delete an item from a dictionary:del student['age'] # Verify that item was deleted 'age' in student > False
-
Use the built-in
len
function to retrieve the number of items in a dictionary:print( student ) > {'name': 'Tina', 'course': 'SEI'} len(student) > 2 len({}) > 0
-
for
loops are used to iterate over the items in a dictionary. However, the following is considered to be a Python anti-pattern:for key in student: print( f"{key} = {student[key]}" )
-
The preferred way is to use the
items()
method to obtain a dictionary view object...
-
The best practice way to iterate over the items in a dictionary is to use a
for
loop to iterate over a dictionary view object as follows:for key, val in student.items(): print( f"{key} = {val}" )
-
The
student.items()
call above returns a wrapped set of tuples:student.items(): > dict_items([('name', 'Tina'), ('course', 'SEI')])
-
The
for
statement "unpacks" the tuples by assigning its values to multiple variables like withkey, val
above.
-
Define a Python dictionary named
where_my_things_are
containing a few items; where thekeys
are things you have, and thevalue
is the location you keep those things. -
Write a
for
loop that iterates over the items in the dictionary and prints each one as My [thing] is kept [location].
-
Lists are to Python as arrays are to JS.
-
A list provides a container for zero or more items (elements).
-
Lists can contain items of different types, including dictionaries and nested lists.
-
Lists have a class (type) of
list
.
-
Like arrays in JS, a list is created with a set of square brackets:
colors = ['red', 'green', 'blue']
-
The number of items in a list is returned using the built-in
len()
function:len(colors) > 3
Lists have the following features:
-
They are considered to be a sequence type in Python. A sequence is a generic term used for an ordered collection. Other sequence types in Python include strings and tuples.
-
Lists are mutable:
- Items within the list can be replaced
- Items can be added and removed from a list
-
Accessing the individual items of a list is much like accessing elements in a JS array, i.e., by using square brackets with an expression that evaluates to an integer:
idx = 1 colors[idx + 1] > blue
-
However, unlike in JS, we can use negative integers to index from the end of a list:
colors[-1] > blue
No need to write code like
colors[len(colors) - 1]
- yay!
-
We also use square brackets to target an item of a list for assignment:
colors[-1] = 'brown' print(colors) > ['red', 'green', 'brown']
-
Unlike with JS arrays, assigning to a non-existing index results in an error.
-
The equivalent to JS's
push()
method isappend()
:colors.append('purple')
However, unlike JS's
push()
method,append()
can only add one item and does not return a value. -
For adding multiple items, use the
extend()
:colors.extend(['orange', 'black'])
-
To add items to anywhere but the end of a list, use the
insert()
method:print(colors) > ['red', 'green', 'brown', 'purple', 'orange', 'black'] colors.insert(1, 'yellow') > ['red', 'yellow', 'green', 'brown', 'purple', 'orange', 'black']
-
Yup, there's a
pop()
method, but it's more flexible in Python because you can specify the index of the item to remove and return:print(colors) > ['red', 'yellow', 'green', 'brown', 'purple', 'orange', 'black'] green = colors.pop(2) print(colors) > ['red', 'yellow', 'brown', 'purple', 'orange', 'black']
-
If you don't care about the value returned by
pop()
, you can also use thedel
operator to delete items:print(colors) > ['red', 'yellow', 'brown', 'purple', 'orange', 'black'] del colors[1] print(colors) > ['red', 'brown', 'purple', 'orange', 'black']
-
Also there's a
remove()
method that removes the first item that matches what you pass in:print(colors) > ['red', 'brown', 'purple', 'orange', 'black'] colors.remove('orange') print(colors) > ['red', 'brown', 'purple', 'black']
No value is returned by the
remove()
method.
-
Lastly,
clear()
does just what it's name implies:print(colors) > ['red', 'brown', 'purple', 'black'] colors.clear() print(colors) > []
-
The
for in
loop is used to iterate over the items in a list:colors = ['red', 'green', 'blue'] for color in colors: print(color) > red > green > blue
-
If we need to access the index of the item while iterating a list, we use the built-in
enumerate()
function to provide the index and the value to afor
loop:for idx, color in enumerate(colors): print(idx, color) > 0 red > 1 green > 2 blue
-
What are dictionaries similar to in JS?
-
What are lists similar to in JS?
-
Why might the following code not work?
menu = { hamburger: 4.99, french_fries: 1.99, taco: 2.99 }
-
What is a way to add items to a list?
-
What is a way to remove an item from the front of a list?
-
One of the most powerful features in Python are list comprehensions.
-
List comprehensions provide a concise way to create and work with lists.
-
They will probably seem a little confusing as first, but they certainly are a favorite of Pythonistas and you will certainly come across them when googling.
-
If we needed to square all of the numbers in a list and put them into a new list, we might use a for loop like this:
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # I want 'n * n' for each 'n' in nums squares = [] for n in nums: squares.append(n * n) print(squares) > [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
-
What method in JS would we use in this scenario?
-
A list comprehension can reduce this code:
# I want 'n * n' for each 'n' in nums squares = [] for n in nums: squares.append(n * n)
To this:
# I want 'n * n' for each 'n' in nums squares = [n * n for n in nums]
-
The comprehension is basically an advanced
for
loop within square brackets which, of course, returns a new list.
-
Here's the basic syntax of a list comprehension:
# [<expression> for <item> in <list>] # This reads as: I want <expression> for each <item> in <list>
-
We've seen how list comprehensions are a nice way to map a list, but they can be used for filtering too.
-
Again, we'll start by using a
for
loop to map and filter simultaneously:nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # I want 'n * n' for each 'n' in nums if 'n * n' is even even_squares = [] for n in nums: square = n * n if square % 2 == 0: even_squares.append(square) print(even_squares) > [4, 16, 36, 64, 100]
-
Again list comprehensions reduce the mapping and filtering from:
# I want 'n * n' for each 'n' in nums if 'n * n' is even even_squares = [] for n in nums: square = n * n if square % 2 == 0: even_squares.append(square)
To this one-liner:
# I want 'n * n' for each 'n' in nums if 'n * n' is even even_squares = [n * n for n in nums if (n * n) % 2 == 0]
Nice and readable!
-
What characters start and end a list comprehension
-
Does a list comprehension create a new list?
-
We've only scratched the surface of list comprehensions.
-
They can even be used to create lists of tuples that would otherwise require nested
for
loops. -
Speaking of tuples...
-
Tuples in Python are very similar to lists.
-
Tuples have a class (type) of
tuple
.
-
Tuples can be defined in a few different ways. Most basically, they are defined like this:
colors = ('red', 'green', 'blue') print(colors) > ('red', 'green', 'blue') print( len(colors) ) > 3
Although it seems that parentheses are used to create tuples, it's actually the commas...
-
For more proof that the use of commas create a tuple, let's say you wanted to create a 1-tuple containing the string of "Hello".
-
If parens created tuples, this would work:
hello_tuple = ('Hello')
But it doesn't, however, this will:
hello_tuple = ('Hello',) # or the following hello_tuple = 'Hello',
-
Tuples can be created without using any parentheses:
colors = 'red', 'green', 'blue' print(type(colors)) > <class 'tuple'>
-
However, creating single-item tuples without parens requires a trailing comma:
colors = 'purple', # tuple, not a string print(type(colors), len(colors)) > <class 'tuple'> 1 print(colors) > ('purple',)
-
Tuples are immutable, so they are great for protecting data that you don't want changed.
-
Python iterates over tuples faster than lists. Tuples can also be used as keys for dictionaries.
-
Generally, you'll find that tuples are used to contain heterogeneous (different) data types and lists for homogeneous (similar) data types.
-
Tuples are often classified based on how many items they contain, e.g., a 2-tuple would be used to hold a
key
and itsvalue
-
Although tuples can't be modified like lists, we can retrieve their items in exactly the same way:
colors = ('red', 'green', 'blue') green = colors[1] print(green) > green
-
Sequences also have an
index()
method that returns the index of the first match:colors = ('red', 'green', 'blue') blue_idx = colors.index('blue') print(blue_idx) > 2
-
Just like with lists, other sequences are iterated upon in the same way - by using
for
loops:colors = ('red', 'green', 'blue') for idx, color in enumerate(colors): print(idx, color) > 0 red > 1 green > 2 blue
-
Tuples (and other sequences such as Lists) have a convenient feature, called unpacking, for doing multiple variable assignment:
colors = ('red', 'green', 'blue') red, green, blue = colors print(red, green, blue) > red green blue
Comma separated variables on the left-side of the assignment operator and a tuple of values on the right is all it takes.
-
Python is known for having some cool tricks up its sleeve, for one, there's the "slice" operator (
[m:n]
). -
Since sequence types are a collection of items (BTW, characters are the items in a string), we can target subsets, called slices, of those items using
[m:n]
.
-
Just like with indexing, slicing uses square brackets, but adds a colon:
short_name = 'Alexandria'[0:4] print(short_name) > Alex
-
Note that the slice includes up to, but not including the index to the right of the colon.
-
If the first index is omitted, the slice copies the sequence starting at the beginning:
colors = ('red', 'green', 'blue') print( colors[:2] ) > ('red', 'green')
-
If the up to index is omitted, the slice copies the sequence all the way to the end:
colors = ['red', 'green', 'blue'] print( colors[1:] ) > ['green', 'blue']
-
What would the value of
fruit_copy
be?fruit = ('apples', 'bananas', 'oranges') fruit_copy = fruit[:]
-
Python offers amazing power, convenience and readability with features such as list comprehensions and slicing.
-
However, as usual, it takes practice to become "comfortable" with these concepts, so on to the lab, but first...
-
True or False: In Python, we use Lists, Tuples & Dictionaries as containers for data.
-
Assuming this dictionary:
fruit = { 'apples': 'red', 'bananas': 'yellow', 'oranges': 'orange' }
Identify the problem with this statement:
color_of_bananas = fruit.bananas