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 to key: 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)


  1. Define a Python dictionary named where_my_things_are containing a few items; where the keys are things you have, and the value is the location you keep those things.
  2. 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 its value



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