Skip to content

Instantly share code, notes, and snippets.

@jim-clark
Last active March 11, 2020 14:35
Show Gist options
  • Save jim-clark/8dc06dcff1d57fc8a6f0b8cee65560c0 to your computer and use it in GitHub Desktop.
Save jim-clark/8dc06dcff1d57fc8a6f0b8cee65560c0 to your computer and use it in GitHub Desktop.

click to view as a presentation


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': '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 - 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(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).


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...


Dictionaries - Iterating Items

  • 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 the keys are things you have, and the value 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

Lists - Accessing Items


  • 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']
  • Unlike with JS arrays, assigning to a non-existing index results in an error.


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']

Lists - Deleting Items


  • 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']

Lists - Deleting Items


  • 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 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

Lists - Iteration


  • 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

  1. What are dictionaries similar to in JS?

  2. What are lists similar to in JS?

  3. Why might the following code not work?

    menu = {
      hamburger: 4.99,
      french_fries: 1.99,
      taco: 2.99
    }
  4. What is a way to add items to a list?

  5. What is a way to remove an item from the front of a list?


List Comprehensions


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?


List Comprehensions
Numerical Example

  • 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]

List Comprehensions - Filtering

  • 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


  1. What characters start and end a list comprehension

  2. Does a list comprehension create a new list?


List Comprehensions - Summary


  • 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


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...


Tuples - Basic Syntax


  • 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 - Basic Syntax


  • 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 (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.


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].


Slicing Sequences


  • 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.


Slicing Sequences


  • 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[:]

Summary


  • 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...


❓ Essential Questions


  1. True or False: In Python, we use Lists, Tuples & Dictionaries as containers for data.

  2. Assuming this dictionary:

    fruit = {
      'apples': 'red',
      'bananas': 'yellow',
      'oranges': 'orange'
    }

    Identify the problem with this statement:

    color_of_bananas = fruit.bananas
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment