Intro to Python Containers
Learning Objectives
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
Setup
To test some of the examples and complete the exercises, please open a Python repl.it
General Purpose Containers
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
Dictionaries - Purpose
-
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
.
Dictionaries - Basic Syntax
Like objects in JS, a dictionary is created with a set of curly braces:
student = {
'name': 'Fred',
'course': 'SEIR',
'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 - Features
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).
Dictionaries - Getting/Setting Values
We use square brackets to get and set an item's value:
name = student['name']
print(name)
> Fred
student['name'] = 'Tina'
print(name)
> Tina
Unlike JS, you cannot access items in a Python dictionary using dot notation (dots are used to invoke methods).
Dictionaries - get Method
Unlike JS which returns undefined
when accessing a property that does not exist, a dictionary will raise a KeyError
.
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
Dictionaries - in Operator
Another way to avoid the KeyError
is to use the in
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")
Dictionaries - Adding Items
Simply assigning to a key that does not exist will create a new item in the dictionary:
student['age'] = 21
Dictionaries - Deleting Items
The del
statement is used to delete an item from a dictionary:
del student['age']
# Verify that item was deleted
'age' in student
> False
Dictionaries - Number of Items
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
Dictionaries - Iterating Items
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 with key, val
above.
💪 Dictionary Practice Exercise - (10 minutes)
-
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
Lists - Purpose
-
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
.
Lists - Basic Syntax
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 - Features
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
Lists - Accessing Items
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!
Lists - Assigning Items
We also use square brackets to target an item of a list for assignment:
colors[-1] = 'brown'
print(colors)
> ['red', 'green', 'brown']
Lists - Adding Items
The equivalent to JS's push()
method is append()
:
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'])
Lists - Inserting Item
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']
Lists - Deleting Items
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 the del
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.
Lists - Clearing
Lastly, clear()
does just what it's name implies:
print(colors)
> ['red', 'brown', 'purple', 'black']
colors.clear()
print(colors)
> []
Lists - Iteration
The for
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 a for
loop:
for idx, color in enumerate(colors):
print(idx, color)
> 0 red
> 1 green
> 2 blue
Dictionary & List Review Questions
❓ What are dictionaries similar to in JS?
❓ What are lists similar to in JS?
❓ Why won't the follow code 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?
List Comprehensions
-
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.
List Comprehensions
Numerical Example
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.
List Comprehensions - Basic Syntax
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>
List Comprehensions - Filtering
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!
List Comprehensions - Review Questions
❓ What characters start and end a list comprehension
❓ Does a list comprehension create a new list?
List Comprehensions - Summary
Keep in mind that we've only scratched the surface of list comprehensions.
If you'd like to see more interactive information on list comprehentions, check out this video, there's a lot of great examples here.
Tuples
Tuples - Purpose
-
Tuples in Python are very similar to lists.
-
Tuples have a class (type) of
tuple
.
Tuples - Basic Syntax
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',)
Differences Between Tuples & Lists
-
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
Tuples - Accessing Items
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
Tuples - Iteration
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 - Unpacking
Tuples 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
A tuple of variables on the left-side of the assignment operator and a tuple of values on the right is all it takes.
Sequences Can Be "Sliced"
Slicing Sequences
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']
Slicing Sequences - Question
What would the value of fruit_copy
be?
fruit = ('apples', 'bananas', 'oranges')
fruit_copy = fruit[:]
Conclusion
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...
Resources
Checkout this Channel on YouTube
they have some amazing content on python
, sql
, and other scientific topics