02-ListsAndLoops
December 11, 2023
1 Adding structure to our data
In this lesson we will learn: - What a list is. - What a loop is. - What a range is. - How to use
lists, ranges, and loops to work with more structure. - What a str (string) is and how it relates to
lists. - Why should I use a list comprehension, and not a loop?
So far we have only considerd variables which hold a singular value. It will often be the case that
you want to do the same operation on a collection of values, or store related values together in a
data structure. Lists are the simpelest way of accheiving both these tasks. However, in time you
will come to have better ways to do both these things using Arrays (numpy) and Dictionaries (built
in python). We use python lists and ranges to teach here for a few reasons: 1. You will end up
using lists and loops when writing python. 2. They are a great entry point to the concepts we need
to learn. 3. They are really useful when used correctly.
1.0.1 Lists
A list in python is simply a collection of data where each element of data can be accessed using
its position.
Let’s start with an example and then break it down the syntax:
[ ]: # Define a list and fill it with a series of data,
# we will call this list my_list abut we could call it anything we like.
my_list = [4, 2.0, 3.4, 7, 9]
# ^ ^
# The [...] characters indicated above are how we declare a list, the opening␣
↪`[` starts the list the closing `]` stops the list.
# In the list we have list elements we can have from no elements, an empty list:
empty_list = []
# To as many elements as we like (up to the storage capacity of the computer␣
↪then things get weird.)
another_list = [2, 3, 4, 5]
# ^ ^ ^
# Elements in a list are seperated by commas, and its good form to follow each␣
↪comma with a space.
Okay, we know now how to create a list by hand* and a few of the properties of the list.
Making lists by hand
1
It’s actually a fairly limted use case, small lists up to ~20 items you may write by hand, so called
hard coded. These lists wont form the majority of your use cases as usually we will want to load
some data put that in a list and then work with it. Until we get to loading data we will continue
with hard coded lists.
We now need to be able to get to specific elements in the list. We will do this using indexing,
each element in a list has an index the indexs start at 0 and end at N-1 where N is the number of
elements in the list.
prime_numbers = [2, 3, 5, 7, 9]
# ^ ^ ^ ^ ^
# Index 0 1 2 3 4
print(prime_numbers[2])
# ^ ^
# variable index
To get a item we use the variable name here prime_numbers then square brackets in which we put
the index to get the third item in the list we use the index 2. The code above would print the
number 5. Copy and paste it into the cell below to try.
We can also use negitive indexes to refrence from the end of the list. For example, in the
above list prime_numbers[-1] is equal to 9 as that is the last element in the list. Furthermore,
prime_numbers[-4] is equal to 3.
Challange Copy the above code and paste it in the cell below then change the index so the code
prints the number 7. Then try and do it with the -ve index.
[ ]:
Lets look at another useful use of a list, this is ‘mutability’. Mutability means that individual
elements of the list can be updated after the list has been created.
fibonacci_sequence = [1,2,3,6,8,13]
In the above sequence I have made a mistake, I have the number 6 where I should have 5. Fortunatly
I dont need to remake the list I can simply update that element of the list.
fibonacci_sequence[3] = 5
I have now changed the value of that element of the list. If we print:
print(fibonacci_sequence)
it would return:
[1, 2, 3, 5, 8, 13]
There is another snag, I’ve forgotton the sequence starts with two ones. Fortunatly I can fix this
as well.
fibonacci_sequence.insert(0, 1)
2
# ^ ^
# index value
Using insert we can insert elements into a list. The first value we give insert is the index that we
want our new value to have, the second thing is the new value.
Now if we print:
print(fibonacci_sequence)
it would return:
[1, 1, 2, 3, 5, 8, 13]
The last thing I will mention here is append. Appending allows for us to add elements to the end
of a list.
fibonacci_sequence.append(21)
I have now added 21 to the end of the list. If we print:
print(fibonacci_sequence)
it would return:
[1, 1, 2, 3, 5, 8, 13, 21]
One last and crutial thing. Lists dont just store numbers you can put pretty much anything inside
a list. Here are a few examples:
my_list_with_text = ["Hi", "text", "can", "go", "in", "lists"]
my_list_with_a_mix = [3, "types", "in", 1.0, "list"]
We will do some more on this later for now let’s write some more code.
1.0.2 Challange: Fix the fizzbuzz
In the cell below I am giving you an array called fizzbuzz. This array should have the first 20
elements of fizzbuzz. However, out of neglagance I have left several elements out and got some
elements wrong. Use the techniques for indexing arrays that you have just learnt to correct the
array.
Add your code between the comment lines. I’ve added a bit of python magic at the end that will
print a message for you to help you build your solution. If you run the cell it will give you the
index of your first mistake and print sucess when done.
Hint 1 - A quick reminder
Remember that the index starts at 0 so if the message reads:
You have an error with fizzbuzz element 18
Then you are looking at the number 19!
Hint 2 - Getting a look at where you are
Don’t expect to get everything correct on your first try. To help you out you could pop in
3
print(fizzbuzz)
to see what your list looks like.
Hint 3 - What the list should look like
[1, 2, ‘fizz’, 4, ‘buzz’, ‘fizz’, 7, 8, ‘fizz’, ‘buzz’ 11, ‘fizz’, 13, 14, ‘fizzbuzz’, 16, 17, ‘fizz’, 19, ‘buzz’]
Hint 4 - Fill in the blanks
fizzbuzz[] = 4
fizzbuzz.insert(7, )
fizzbuzz.insert(, 'buzz')
fizzbuzz[14] = ''
fizzbuzz.insert(17, )
fizzbuzz.append()
[1]: fizzbuzz = [1, 2, 'fizz', 5, 'buzz', 'fizz', 7, 'fizz', 11, 'fizz', 13, 14,␣
↪'fizzz', 16, 17, 'fizz', 19]
#Don't edit above this line␣
↪==========================================================================
fizzbuzz[3] = 4
fizzbuzz.insert(7, 8)
fizzbuzz.insert(9, 'buzz')
fizzbuzz[14] = 'fizzbuzz'
fizzbuzz.append('buzz')
#Don't edit below this line␣
↪==========================================================================
from example_helpers import check_fizzbuzz
check_fizzbuzz(fizzbuzz)
Success the first 20 numbers fizzbuzzed are
[1, 2, 'fizz', 4, 'buzz', 'fizz', 7, 8, 'fizz', 'buzz', 11, 'fizz', 13, 14,
'fizzbuzz', 16, 17, 'fizz', 19, 'buzz']
1.0.3 Solution
Solution for ‘Fix the fizzbuzz’
Here are the steps I used to fix the fizzbuzz list:
fizzbuzz[3] = 4
fizzbuzz.insert(7, 8)
fizzbuzz.insert(9, 'buzz')
fizzbuzz[14] = 'fizzbuzz'
fizzbuzz.append('buzz')
Dont worry if yours dont match mine perfectly as long as you get the sucess message then your
answer is fine.
4
1.0.4 Loops
We can think of loops in a simmilar way to the way we used conditionals in the previous notebook.
They add a kind of logical flow to our code that is in addition to the top to bottom flow that is
the default. The following diagram shows a generic loop, the loop is made of a start point, some
code to be run multiple times, and a condition on which to end the loop.
There are two kinds of loops in Python. The while loop and the for loop*.
The while loop The while loop is the more simple of the two.
# code before the loop
while (a > b):
print('Hello World')
5
# code after the loop
This loop will repeat the code inside the loop for as long as the condition, a > b, evaluates to True.
If the condition isn’t True when we reach the loop it will never run just like an if.
In this course we are not going to use while loops, this is here so if you see one you know what
it is and what it does. In pratice they are discouraged. The reason being if you don’t update the
variables that the condition is checking then the loop will run infinatly and prevent your code from
finishing.
So instead we look at for loops, let’s jump into an example then pick apart the syntax.
*It’s not actually called a for loop
The for loop is actually called an iterator loop because thats what it technically does.
[ ]: # An example of a basic for loop that prints the numbers 1 to 10 to output.
numbers_to_print = [1,2,3,4,5,6,7,8,9,10]
for loop_variable in numbers_to_print:
print(loop_variable)
# Challange: Modify the code so that it prints 'n: Hello world' ten times where␣
↪n is the number
# of times hello world has been printed.
Solution
Replace:
print(loop_variable)
With:
print(loop_varable, ": Hello World")
For Loops The basic syntax of the for loop is - for: This is the keyword that tells the python
interpreter that we are begining a for loop. - loop_variable: This is the variable that will be
changed each time we run the loop, we can give it any name. - in: This keyword lets the python
interpreter know that the next variable is the list we will itereate over. - iterable: This is the
collection that we are going to iterate over.
The new concept here is that of an iterable. In the example we use a list which is an iterable, or it
has some property that we can iterate over. In the case of the example list this is the values from
1 to 10. More generically it is each element of the list in turn. In the rest of this notebook we will
meet two other useful iteratables.
However, this seems a little cart leading horse. We had to write the numbers one to 10 in a list to
get the code to print the numbers 1 to 10. This is where our next iterable range comes in, with
range we need to specify the start and end (inclusive, exclusive) then it will generate numbers in
that range whenever called by an iterator such as a for loop.
Let’s put it to use:
6
[2]: # Remember the range is exclusive of the stop value so to get the numbers 1 to␣
↪10 we need to set the upeer as 11
for i in range(1,11):
print(i)
1
2
3
4
5
6
7
8
9
10
Putting everything covered thus far together we can start to build more complex programs.
To build out the complexity we need to thing about nesting. Nesting is the process of having one
block within another, for example:
# Main code
for first_loop_var in first_loop_iterable:
# Block 1 code
if my_condition:
# Block 2 code
for second_loop_var in second_loop_iterable:
# Block 3 code
# Block 2 code
# Block 1 code
# Main code
In the above code we have the main code and three blocks, the # Main code will always run. The
loop then creates the first block, block 1, we recognise the block by the indentation. The condition
creates the next block, block 2, indented by 4 more spaces for a total of 8 spaces. Finally the second
loop creates the innermost block, block 3, indented by 12 spaces total (3*4spaces).
The indentenion of each block is consistent to make code more readable. We can nest many many
times, however, the practical limit of nesting is far less than the computational limit. Using nested
structures we can create complex data processing structures, branching logical conditions and much
more.
7
1.0.5 Challange
The next challange is to use the loops and lists in combonation with the conditional logic to fizzbuzz
the numbers 1-100 and store the output in a list called output.
Hint 1: How to start
Head over to draw.io. And create a logicial flow diagram.
Hint 2: The partial solution to hint 1
8
9
Hint 3: The full solution to hint 1
10
11
Hint 4: Some fill in the blanks code
output = []
for i in range(1,101):
# check if the modulus of the number is 0 if it is its a multiple!
is_i_f = TEST
is_i_b = TEST
# if both multiples then we need to fizzbuzz
is_i_fb = is_i_f and is_i_b
if CONDITION:
loop_var = ''
elif CONDITION:
loop_var = ''
elif CONDITION:
loop_var = ''
else:
VARIABLE = i
output.append(loop_var)
print(output)
[ ]: # Don't change the code below this line
from example_helpers import check_fizzbuzz
check_fizzbuzz(output, 100)
Solution
output = []
for i in range(1,101):
# check if the modulus of the number is 0 if it is its a multiple!
is_i_f = i%3 == 0
is_i_b = i%5 == 0
# if both multiples then we need to fizzbuzz
is_i_fb = is_i_f and is_i_b
if is_i_fb:
loop_var = 'fizzbuzz'
elif is_i_f:
loop_var = 'fizz'
elif is_i_b:
loop_var = 'buzz'
else:
loop_var = i
output.append(loop_var)
12
# Don't change the code below this line
from example_helpers import check_fizzbuzz
check_fizzbuzz(output, 100)
1.1 Strings
The next thing to add to our Python toolkit is the string. A string or str is another Python
type, it’s also iterable and indexable.
my_string = 'Hello World'
Strings are a useful type in Python. In many ways they operate simmilar to lists, so everything we
know about indexing and iterating is also applicable to strings.
Some more list and string simmilarities.
Concatanation Concatanation is when we combine two strings or arrays to create a longer array.
Here is an example for lists and strings:
[1,2,3] + [4,5,6] = [1, 2, 3, 4, 5, 6]
'abc' + 'def' = 'abcdef'
Lists and strings can both overload* the + operator to concatinate the arrays and strings.
*Operator overloading
Overloading is the term we use describe when an operator can have different effects depending on
the datatypes they are operating on. As an example + can:
• Add two numbers
• Act as and between two bool
• Act as a concatination between pairs of str or list
There are many many overloads that appear in python. However as they tend to appear naturally we
won’t list them but when you see a operator doing somthing new you now know what is happening.
Slicing Slicing is a fancy form of indexing for lists and strings. We can access a range of elements
by specifying two elements seperated by a :.
full_list = [3,1,4,1,5,9,2,6,5]
sub_list = full_list[2:5]
print(sub_list)
Output:
[4, 1, 5]
and again with strings:
full_list = "Hello World"
13
sub_list = full_list[6:10]
print(sub_list)
Output:
Worl
1.1.1 Challange
Edit the following list slicing to make the output print ‘ello’
[3]: full_list = "Hello World"
sub_list = full_list[1:5]
print(sub_list)
ello
Solution
full_list = "Hello World"
sub_list = full_list[1:6]
print(sub_list)
1.1.2 Mutability
This is a important distinction between lists and strings. Lists are mutable strings are immutable.
This means in lists we can update individual elements using their index, strings are set when they
are created.
Let’s look at some examples.
This is valid:
my_list = [1,2,3,4,5,6]
my_list[3] = "I can change elements"
This will raise and error:
my_string = "Thi5 cant be changed"
my_string[3] = "s"
1.2 Advanced Topic
If you are struggling with the content up to this point then skip to the section titled List Compre-
hensions.
The following is more conceptually advanced. However, it will help with understanding of what
Python is and is not good at. This in turn will help you write effective Python and motivate some
of the choices commonly made when using Python for scientific computing.
14
1.2.1 Why we shouldn’t use lists and loops.
We have touched on Python being an intrepreted language already. Interpreted languages are great
for quick prototyping an rapid iterations. However, intrepreted languages can be slow if written
incorrectly. Applying this to Python we learn why we cant write lists and loops and expect fast
results.
Let’s consider how the interpreter processses code, and introduce a little bit of magic in the
%%timeit* cell magic which can tell us on average how long it takes to run a cell.
%%timeit
First thing to note %%timeit isnt python it’s part of the notebook we are working in. Timeit runs
the code several times and reports to us how quickly it ran.
[4]: evens_odds = []
for i in range(1, 101):
if i%2:
ret = 'odd'
else:
ret = 'even'
evens_odds.append(ret)
print(evens_odds)
['odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even',
'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even',
'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even',
'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even',
'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even',
'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even',
'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even',
'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even',
'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even',
'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even']
[11]: %%timeit -o
evens_odds = []
for i in range(1, 101):
if i%2:
ret = 'even'
else:
ret = 'odd'
evens_odds.append(ret)
7.72 µs ± 444 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
15
[11]: <TimeitResult : 7.72 µs ± 444 ns per loop (mean ± std. dev. of 7 runs, 100,000
loops each)>
[6]: # This is another bit of python magic to collect the time from above.
loop_time = _
1.2.2 Speeding things up
So lets look at some faster code, then we can try and unpick whats happening. The following is
called a list comprehension. A list comprehension is a way of compressing the generation of a list
into a single line. We use them to make a quicker version of the loop above. We will go into how
to construct a list comprehension later, for now run the next cells in order and read the output.
[7]: evens_odds = ['odd' if i%2 else 'even' for i in range(1, 101)]
print(evens_odds)
['odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even',
'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even',
'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even',
'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even',
'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even',
'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even',
'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even',
'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even',
'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even',
'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even']
[8]: %%timeit -o
evens_odds = ['odd' if i%2 else 'even' for i in range(1, 101)]
5.05 µs ± 62.6 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
[8]: <TimeitResult : 5.05 µs ± 62.6 ns per loop (mean ± std. dev. of 7 runs, 100,000
loops each)>
[10]: # This is another bit of python magic to collect the time from above.
comp_time = _
[12]: # Get the percentage speedup between the two methods.
percent_speedup = 100-(comp_time.average/loop_time.average)*100
print(f"Percentage speedup is {percent_speedup:0.1f}%")
Percentage speedup is 28.4%
1.2.3 Explanation
In each of these examples we test how quickly we can test if the first 100 numbers are odd or even.
16
This is a simple example but it serves to highlight what is happening.
In simplistic terms the interptrer goes from line to line evaluates the line and then sends the
commands to the processor. To calculate odds and evens in a loop:
First the interprter tells the processor to create the array
evens_odds = []
The processor is instructed to loop to run 100 times
for i in range(1, 101):
i has been set to 1 the processor checks if i is divisible by 2 fails and skips to the next part of the
control sequence
if i%2:
the processor meets else and enters the code block.
else:
the processor sets ret to ‘odd’
ret = 'odd'
the processor appends the value of ret to the end of evens_odds
evens_odds.append(ret)
i has been set to 2 the processor checks if i is divisible by 2 passes and enters the code block
if i%2:
the processor sets ret to ‘even’
ret = 'even'
the processor appends the value of ret to the end of evens_odds
evens_odds.append(ret)
This process continues for 98 more loop iterations.
The intepreter is processing 350 lines to send all the commands to the processor.
For the next peice of code
evens_odds = ['odd' if i%2 else 'even' for i in range(1, 101)]
The processor is told to make a list by evaluating the numbers 1 to 100 adding ‘odd’ or even based
on the condition.
The intrepreter processes one line to send all the commands to the processor.
In this scenario the task was essentially the same but for each intrepreted line there is a small
amount of overhead in the loop we repeat this overhead 350 times and in the comprehension we
only need it once.
17
1.2.4 Writing list comprehensions
List comprehensions are an excellent way to make your code look neater and run faster.
A simple example of a list comprhension is to create a list of the numbers one to one hundred.
my_simple_listcomp = [ i for i in range(1,101) ]
# ^
# This is the value the list element will take.
It’s useful to see this as a mixture of a for loop and a list. The for loop iterates over range(1,101)
each time it assigns the value to the variable i. In this list comprehension we dont do anything
with the variable i so the value of i becomes the list value.
Introducing a simple conditional we can filter the values. To create a list of only even numbers:
evens_only = [ i for i in range(1,101) if i%2==0 ]
# ^^^^^^^^^^^
# Add a condition to filter
The filter prevents that element being added to the list, so this list is only 50 elements long.
The final addition to the list comprehension is an expression. You can use the loop variable in an
expression that will be evaluated every time the condition passes.
squares_of_evens = [ i**2 for i in range(1,101) if i%2==0 ]
# ^^^^
# i is raised to the power 2
Here we raise even values of i to the power 2. In actuality we would ususaly use a more intresting
or useful expression.
1.2.5 Challange
Write two list comprehensions one that fizzes and one that buzzes for the numbers one to one
hundred. e.g. fizz_comp should create [1,2,'fizz',4,5,'fizz...]
Hint 1
You need to use a range iterator from 1 to 101
Hint 2
You need to use an if else expression
Hint 3
Use i%3 or i%5 depending on if you are fizzing or buzzing
Hint 4 Fill in the blanks
Replace the underscores. [ ___ if ___ else ___ for i in ___]
[ ]: fizzed =
buzzed =
# Don't change the code below this line
18
from example_helpers import check_fizz, check_buzz
check_fizz(fizzed, 100)
check_buzz(buzzed, 100)
Solution
fizzed = [i if i%3 else 'fizz' for i in range(1,101)]
buzzed = [i if i%5 else 'buzz' for i in range(1,101)]
1.2.6 Enumeration
The use of loops, ranges, and list comprhensions should begin to give an idea of how important
iterables are to Python. It’s to be expected that python has many ways to work with iterables.
Enumeration is one such method. Let’s take a look:
[13]: my_list =␣
↪[1,2,'fizz',4,'buzz','fizz',7,8,'fizz','buzz',11,'fizz',13,14,'fizzbuzz']
for i in enumerate(my_list):
print(i)
(0, 1)
(1, 2)
(2, 'fizz')
(3, 4)
(4, 'buzz')
(5, 'fizz')
(6, 7)
(7, 8)
(8, 'fizz')
(9, 'buzz')
(10, 11)
(11, 'fizz')
(12, 13)
(13, 14)
(14, 'fizzbuzz')
We pass enumerate an iterable and it returns a pair of items the index and the value. For each
pass though the loop enumrate assigns i the pair of values (index, value). We can make this more
user frindly by unpacking the output of enumerate, another example:
[14]: my_list =␣
↪[1,2,'fizz',4,'buzz','fizz',7,8,'fizz','buzz',11,'fizz',13,14,'fizzbuzz']
for i, value in enumerate(my_list):
print('Index:', i, 'Value:', value)
Index: 0 Value: 1
19
Index: 1 Value: 2
Index: 2 Value: fizz
Index: 3 Value: 4
Index: 4 Value: buzz
Index: 5 Value: fizz
Index: 6 Value: 7
Index: 7 Value: 8
Index: 8 Value: fizz
Index: 9 Value: buzz
Index: 10 Value: 11
Index: 11 Value: fizz
Index: 12 Value: 13
Index: 13 Value: 14
Index: 14 Value: fizzbuzz
This is exactly the same as we have had previously only we allow the for loop to use two loop
variables.
1.3 Challange fizzbuzz in list comprehensions
Use what you have learnt about list comprehensions to create a fizzbuzz.
Feel free to pick a difficulty here getting this done in one line requires nesting list comprhensions.
Here is an example of a nested list comphension:
nested_list_comprehension = [ j if j%5 else 'buzz'
for j, value in enumerate(
[ i if i%3 else 'fizz'
for i in range(1,101)
]
)
]
This dosent look quite like one line! What python is doing is finding the first [ then waiting until
it finds its closing ]. It will run just the same with or without the newlines, the new lines do
however make this a lot more readable. The tirck here is the interpreter will only be sending the
one command to the processor.
Difficulty Medium: Use three list comprhensions (not nested) Assign the final result to
fizzbuzz_list_comp.
Hint 1
First make a fizzed list like above.
Then enumerate the fizzed list in a list comp to apply buzz to get a fizzed_then_buzzed list.
Finally, enumerate the fizzed_then_buzzed list to apply the fizzbuzz.
Hint 2
Add the expressions:
20
fizzed = [...]
fizzed_then_buzzed = [... for i, value in enumerate(fizzed)]
fizzbuzzed_list_comp = [... for i, value in enumerate(fizzed_then_buzzed)]
Hint 3
Remember about zero indexing when using enumerate!
Hint 4
The final expression to pick out the fizzbuzzed uses an and to combine smaller conditions.
Difficulty Hard: Use nested list comphrensions (three nesting levels) Assign the list
comprehension to fizzbuzz_list_comp.
Hint 1
Do the medium first then try to combine your results.
Hint 2: How to get half way
You will have made two lists in the medium version fizzed and fizzed_then_buzzed.
Where you made fizzed_then_buzzed you passed fizzed to enumerate. Try to make
fizzed_then_buzzed in a single line by replacing the contents of enumerate with the code you
used to make fizzed.
Hint 3
Simmilarly to how fizzed_then_buzzed was made directly we can substitute the whole of
fizzed_then_buzzed into another list comprhensions enumerate.
[ ]: fizzbuzz_list_comp = ['''Write your list comp in here''']
# Don't edit below this line
from example_helpers import check_fizzbuzz
check_fizzbuzz(fizzbuzz_list_comp, 100)
1.4 Solutions
Medium Version
Splitting each over multiple lines to make the list comprehensions more readable
fizzed = [i if i%3 else 'fizz'
for i in range(1,101)]
fizzed_then_buzzed = [j_value if (j+1)%5 else 'buzz'
for j, j_value in enumerate(fizzed)]
fizzbuzz_list_comp = ['fizzbuzz' if ((k+1)%3==0 and (k+1)%5==0) else k_value
for k, k_value in enumerate(fizzed_then_buzzed)
21
]
Hard Version
Some serious nesting, well done if you got this. However, it’s probably at a level of obfuscation
that we wouldnt do this in practice.
fizzbuzz_list_comp = ['fizzbuzz' if ((k+1)%3==0 and (k+1)%5==0) else k_value
for k, k_value in enumerate(
[j_value if (j+1)%5 else 'buzz'
for j, j_value in enumerate(
[i if i%3 else 'fizz'
for i in range(1,101)
]
)
]
)
]
1.5 Done
Thats it for this section, if you want to do more try running %%timeit on the list comp vs looped
fizzbuzz. Or have a play with anything else thats intrested you in the cell below. (Remember dont
print in a %%timeit cell!)
[ ]:
1.6 Next Section
03-Functions
22