
After this lesson, you will be able to:
itertools to implement efficient looping.A key part of programming is “Don’t Repeat Yourself:”
Programmers aren’t lazy — they’re efficient!
Python is filled with functionality that has already been written for you.
lists.append() — you just use it!Code abstraction takes this to the next level.
We’re going to look at just a few of these.
Let’s look at itertools.
Using itertools, this is what we’ll learn to do in the following slides:
# We can group list items:
animals = ['dog', 'dog', 'dog', 'horse', 'horse']
# => dog ['dog', 'dog', 'dog'] - The three dogs are grouped together.
# => horse ['horse', 'horse'] - The two horses are grouped together.
# We can chain lists:
food = ['pizza', 'tacos', 'sushi']
colors = ['red', 'green']
# => lists_chained =['pizza', 'tacos', 'sushi', 'red', 'green']
# We can add elements:
primes = [2, 3, 5, 7, 11, 13]
# => primes_added = [2, 5, 10, 17, 28, 41]groupby()Sometimes, our lists contain repeated items that work better for us if they are all grouped together. Using groupby(), which Python has written for us in itertools, we can take our list and group the items.
key: The name of the group (in this case dog and horse).group: A list containing all occurrences of that key from the original list.groupby()All the gibberish-looking stuff is memory addresses. Python tells us, “I made a new object and I put it here.” We’ll talk about this on the next slide.
Everything on your computer has to be stored somewhere! Computers track where things are by assigning them memory addresses. This way, when you want to open a picture or file, your computer knows exactly where to look.
But that memory address isn’t useful. We can use list() to change the address back into a list. (list() is explicit typecasting; do you remember it?)
dog There Twice?This is our original list:
animals = ['dog', 'dog', 'horse', 'horse', 'horse', 'dog']
groupby() gives us this:
dog ['dog', 'dog']
horse ['horse', 'horse', 'horse']
dog ['dog']
Can anyone guess why dog is listed twice?
groupby() is great, but not perfect! It will only group consecutive items. Always run groupby() on a sorted list (if you forget, you’ll remember when groupby() returns something strange!).
Can Python sort lists? - Yes! Everything useful is built in. - There’s a sorted() function: new_sorted_list = sorted(list_to_be_sorted).
groupby() Be Useful?What if we had a list of tuples? It’s a bit hard to read.
We could use groupby() to get this:
animal:
wolf is a animal
sparrow is a animal
plant:
cactus is a plant
vehicle:
yacht is a vehicle
school bus is a vehicle
car is a vehicle
We’ve looked at our first itertool, groupby(). It groups things in lists, tuples, etc. — any collection — by keys.
key: The name of the group (in this case dog and horse).group: A list containing all occurrences of that key from the original list.groupby() needs to be run on something sorted. We can sort with another built-in function: sorted(list_to_be_sorted).
We only worked on lists, but tuples are a better use case for groupby(). groupby() can be run on any collection.
import itertools
animals = ['dog', 'dog', 'horse', 'horse', 'horse', 'dog']
sorted_animals = sorted(animals)
print("Now sorted, the list is:", sorted_animals, "\n")
for key, group in itertools.groupby(sorted_animals):
print(key, list(group))Up next: chain()!
chain()With itertools, we can chain lists:
food = ['pizza', 'tacos', 'sushi']
colors = ['red', 'green']
# => lists_chained =['pizza', 'tacos', 'sushi', 'red', 'green']The chain() function takes any number of lists or sequences as parameters to turn into one. - chained_list = list(itertools.chain(list1, list2, list3))
Question: Why not just use +?
Answer 1: itertools.chain is more efficient — it’s faster, even if it’s still too fast for you to notice the difference.
Answer 2: itertools.chain can contain different types of iterables.
import itertools
food_list = ["apples", "bananas", "oranges"]
numbers_range = range(4)
colors_dictionary = {
"green": "peaceful",
"blue": "calm",
"red": "passionate"
}
# ✅ THIS WORKS. YAY!
chained_list = list(itertools.chain(food_list, numbers_range, colors_dictionary))
# => ['apples', 'bananas', 'oranges', 0, 1, 2, 3, 'green', 'blue', 'red']
# 🚫 THIS DOES NOT WORK. DON'T DO IT!
chained_list = food_list + numbers_range + colors_dictionarychain()Create a local file, my_itertools.py. Put this at the top:
import itertools
Below that:
chain() AnswerOur second itertool is chain(), which puts lists and other collections together.
The chain() function takes any number of lists or sequences as parameters to turn into one.
import itertools
food_list = ["apples", "bananas", "oranges"]
numbers_range = range(4)
colors_dictionary = {
"green": "peaceful",
"blue": "calm",
"red": "passionate"
}
chained_list = list(itertools.chain(food_list, numbers_range, colors_dictionary))
# => ['apples', 'bananas', 'oranges', 0, 1, 2, 3, 'green', 'blue', 'red']Up next: accumulate()!
accumulate()What else can we do with itertools? - We have groupby() and chain().
We can accumulate elements — add each index as it goes, making a new list with all the sums.
primes = [2, 3, 5, 7, 11, 13]
# => primes_added = [2, 5, 10, 17, 28, 41]
# How? It adds what's before it.
# [(2), (2+3=5), (5+5=10), (10+7=17), (17+11=28), (28+13=41)]Pro tip: It’s like the Fibonacci sequence!
accumulate()Run this. Try changing the numbers! Set some to negative or floats.
Those are all the itertools we’re going to cover!
groupby(): Grouping items in our list or collection.chain(): Concat lists or collections into one longer list.accumulate(): Add each element throughout a list, making a new list.### Chain ###
food = ['pizza', 'tacos', 'sushi']
colors = ['red', 'green']
# => lists_chained =['pizza', 'tacos', 'sushi', 'red', 'green']
### Groupby ###
# Make our list.
animals = ['dog', 'dog', 'horse', 'horse', 'horse', 'dog']
for key, group in itertools.groupby(animals):
# Key: the name of the group. Group: the items in it.
print(key, group)
### Accumulate ###
primes = [2, 3, 5, 7, 11, 13]
# => primes_added = [2, 5, 10, 17, 28, 41]Up next: List comprehensions.
itertools provides abstraction for iterating over lists. We’re done with them!
Let’s move on. What about building a new list that’s slightly modified from another list? This is extremely common, so Python provides us with list comprehensions.
For anything where you can make:
You can use list comprehension syntax instead:
It turns three lines of code into one!
So, instead of our for loop, we can have # new_list = [modification old_list [condition]].
Let’s run this. Try changing the list or modification.
How could we only square the even numbers?
We’re familiar with a loop:
# All squares
for i in old_list: # old list
squares.append(i**2) # modification
# Even squares
for i in old_list: # Old list
if i % 2 == 0: # Conditional
squares_even.append(i**2) # ModificationNow, in a list comprehension:
# new_list = [modification old_list [condition]]
squares = [i**2 for i in old_list]
# Even squares: The condition is the `if` statement!
squares_even = [i**2 for i in old_list if i % 2 == 0]Let’s run this. Try changing the list, modification, or conditional. It’s # new_list = [modification old_list [condition]].
We’re not limited to math or numerical lists! Any list will work and any if conditional will work.
If you can make:
Then you can make:
Let’s say we have a string containing both numbers and letters:
We want to write a list comprehension that will make a new list containing only the numbers that appear.
modification?old_list_iteration?condition?Get with a partner! Pick a driver.
Below, turn the for loop into a list comprehension. Discuss with them: Why doesn’t it print [99, 13, 2]?
Code abstraction: Shortcut functions provided by Python for common tasks.
itertools:
Abstraction for loops and iterating.
groupby(): Creates groups of elements in a list matching a key. Sort elements first!
animals = ['dog', 'dog', 'dog', 'horse', 'horse', 'horse'] and for key, group in itertools.groupby(animals) creates dog: ['dog', 'dog', 'dog'], horse: ['horse', 'horse']chain(): Creates one long list from many lists.
chained_list = list(itertools.chain(list1, list2, list3))accumulate(): Performs some operation on a list and returns the accumulated results.
results = list(itertools.accumulate(primes))List comprehensions: - Abstraction for creating a slightly modified list. - new_list = [modification old_list_iteration [condition]]