Quick introduction to Python¶

Browse files online

REQUIREMENTS:

• THIS WORKSHEET IS INTENDED FOR PEOPLE WHO ALREADY HAVE PROGRAMMING SKILLS, and in 3-4h hourse want to rapidly get an idea of Python

• Having installed Python 3 and Jupyter: if you haven’t already, have a look at Installation

IF YOU ARE A BEGINNER:

Skip this worksheet and do instead the tutorials you find in the section Foundations, starting from Tools and scripts

What to do¶

• extract the zip in a folder

The notebook file MUST be in the extracted folder.

Otherwise it won’t be properly visualized!

you should obtain something like this:

quick-intro
quick-intro.ipynb
quick-intro-sol.ipynb
jupman.py

ONLY USE PYTHON 3 in this book

• If by chance you get surprising behaviours, check you are actually using Python 3 and not the 2.

• If by issuing python your operating system by chance runs python 2, try executing instead the command python3

• open Jupyter Notebook in that folder. Two things should open, first a console and then a browser. The browser should show a list of files: browser the list and open the notebook quick-intro.ipynb

• Keep reading the exercises file, every now and then you will find inside EXERCISE headers, which will ask you to write Python commands in the following cells. The exercises are marked by difficulty, from ✪ to ✪✪✪✪ stars

Always remember to execute the first cell inside the notebook.

It contains instructions like import jupman which tell Python which modules are needed and how to find them. To execute it, see the following shortcuts

Keyboard shortcuts for Windows and Linux users:

• To execute Python code inside a Jupyter cell, hit Ctrl+Enter

• To execute Python code inside a Jupyter cell AND select the following cell, hit Shift+Enter

• To execute Python code inside a cell AND create a new cell right afterwards, hit Alt+Enter

• If by chance the Notebook looks stuck, try selecting Kernel -> Restart

If you are a Mac user, substitute above keys with the following:

• Ctrl -> Command key

• Shift -> Shift

• Alt -> Option

Let’s try Jupyter¶

Let’s briefly have a look at how Jupyter notebooks work.

EXERCISE: Try inserting a Python command: write in the cell below 3 + 5, and while you are in the cell hit the special keys Control+Enter. As a result, you should see the number 8

[ ]:

EXERCISE: in Python we can write comments by starting a row with a crosshair #. As before, write in the cell below 3 + 5 but this time write in the row below the writing # write here:

[2]:
# write here

EXERCISE: for each cell Jupyter shows the result only in the last executed row in that cell. Try inserting this code in the cell below and execute by hitting Control+Enter. What is the result?

3 + 5
1 + 1
[3]:
# write here

EXERCISE: Let’s try creating a new cell

• While you have the cursor in this cell, hit Alt+Enter. A new cell should open after the current one.

• In the newly created cell, insert 2 + 3 and then hit Shift+Enter. What happens to the cursor? Try the differences with Control+Enter. If you don’t understand the difference, try hitting Shift+Enter repeatedly and see what happens.

Main types of data in Python¶

Since the book’s theme is data processing, to start with we will focus on data types in Python.

References:

Whenever we read data from an external data source like a file, we will inevitably be forced to embed the data we read into some combination of these types:

Type

Exemple 1

Exemple 2

Exemple 3

int

0

3

-5

float (floating point number)

0.0

3.7

-2.3

bool

False

True

string

""

"Good morning"

'How are you?'

list

[]

[5, 8, 10]

["give me", 5, "something"]

dict

{}

{'key 1':'value 1', 'key 2':'value 2'}

{5:'a string value', 'some strin g key':7}

Sometimes we will use more complex types, for example we could store temporal values into the type datetime which can also hold the timezone.

In what follows, we will provide some brief example about what we can do on various data types, putting references to more detailed explanations in the book.

Integer and floating point numbers¶

We put here a couple of brief notes.

References:

In Python we have integer numbers:

[4]:
3 + 5
[4]:
8

The sum between integers obviously gives us an integer:

[5]:
type(8)
[5]:
int

What if we divide integers? We will find the floating point type float:

[6]:
3 / 4
[6]:
0.75
[7]:
type(0.75)
[7]:
float

BEWARE of the dot !

Might be in your country you are used to express decimals with a comma ,: note in Python and in many data formats, you always have to use the dot . format.

✪ EXERCISE: Try writing down here 3.14 with the dot, then 3,14 with a comma and execute with Ctrl+Enter. What happens in the two cases?

[8]:
# write here with the dot

[9]:
# write here with the comma

✪ EXERCISE: Try writing down here 3 + 1.0 and execute with Ctrl+Enter. What is the result type? Check also using the command type.

[10]:
# write here the commands

✪ EXERCISE: Some math professor must have surely warned you to never divide by zero. Python doesn’t like it neither. Try writing in the cell below 1 / 0 and then hit Ctrl+Enter to execute the cell, note Python will show the row where the error happened:

[11]:
# write here the code

Booleans - bool¶

Booleans represent true and false values, and we can use them to verify when some condition happens.

References

To denote booleans, Python provides two constants True and False. What can we do with them?

and operator¶

We might use them to save in variables whether or not a certain fact happened, for example to start the day we might make a program which tells us we can exit home only if we both had breakfast and cleaned teeth:

[12]:
breakfast = True
cleaned_teeth = True

if breakfast and cleaned_teeth:
print("done everything !")
print("can exit home")
else:
print("CAN'T exit home")

done everything !
can exit home

✪ EXERCISE: try to manually write down here the program from the previous cell, and execute it with Ctrl+Enter. Try changing the values from True to False and see what happens.

Make sure to try all these cases:

• True True

• True False

• False True

• False False

WARNING: Remember the : at the end of the if row !!!!

[13]:
# write here

You can also place an if inside another, obtaining a so called nested if. For example, this program works exactly as the previous one:

[14]:
breakfast = True
cleaned_teeth = True

if breakfast:
if cleaned_teeth:                        # NOTE: This if block is indented
print("done everything !")           #       w.r.t the   if breakfast
print("can exit home")
else:
print("CAN'T exit home")
else:
print("CAN'T exit home")
done everything !
can exit home

✪ EXERCISE: Try modifying the previous program to report the state of the various actions that were executed. We list here the possible cases and expected results:

• True False

didn't clean teeth
CAN'T exit home
• False True

• False False

didn't have breakfast
CAN'T exit home
• True True

cleaned teeth
done everything !
can exit home !

Show solution
[15]:

# write here

or operator¶

To verify if at least one of the two conditions has occurred, we can use the or operator. For example, let’s say that in order to have breakfast we need some whole or skimmed milk. Of course, we should have breakfast also when we have both!

[16]:
have_whole_milk = True
have_skimmed_milk = False

if have_whole_milk or have_skimmed_milk:
print("can have breakfast !")
else:
print("CAN'T have breakfast :-(")
can have breakfast !

✪ EXERCISE: try to manually write down here the program from the previous cell, and execute with Ctrl+Enter. Try changing values from True and False and see what happens:

Be sure to try all cases:

• True True

• True False

• False True

• False False

[17]:
# write here

✪✪ EXERCISE: try writing a program which tells you can exit home only if you had breakfast (so you need at least one kind of milk) and cleaned teeth. Make sure to try the program with all the possible combinations.

Show solution
[18]:
have_whole_milk = False
have_skimmed_milk = True

cleaned_teeth = False

# write here

can have breakfast !
CAN'T exit home

not operator¶

For negations, you can use the not operator:

[19]:
not True
[19]:
False
[20]:
not False
[20]:
True
[21]:

print("I'm hungry !")
else:
print("the cereals were so good")
I'm hungry !
[22]:

print("I' hungry !")
else:
print("the cereals were so good")
the cereals were so good

✪✪ EXERCISE: try writing a program which tells you can swim if you DIDN’T have breakfast AND you have a life jacket

Be sure to try all cases:

• True True

• True False

• False True

• False False

Show solution
[23]:

have_life_jacket = True

# write here

you CAN'T swim

Beyond True and False¶

BEWARE of booleans different from True and False !

In Python, the number 0 and other ‘null’ objects (like the object None, the empty string "" and the empty list []) are considered False, and everything which is not ‘null’ is considered True!

Let’s make an example with regular booleans:

[24]:
if True:
print("this")
print("will")
print("be printed")
else:
print("this other one")
print("won't be printed")
this
will
be printed

Everything which is not null is considered True, so let’s try using the string "hello" instead of True:

[25]:
if "hello":
print("this also")
print("will be printed!!")
else:
print("this won't")
this also
will be printed!!
[26]:
if False:
print("I won't be printed")
else:
print("I will")
I will
[27]:
if 0:
print("this also won't be printed")
else:
print("I will")
I will
[28]:
if None:
print("this won't be printed neither")
else:
print("I will")
I will
[29]:
if "":  # empty string
print("Not even this one will be printed!!!")
else:
print("I will")
I will

✪ EXERCISE: Copy down here the if with a space " " inside the if condition. What will happen?

• try also to place an empty list [], what happens?

Show solution
[2]:

# write here the if

Strings - string¶

Strings are immutable sequences of characters.

References:

Concatenating strings

One of the most frequent things you do is concatenating strings:

[31]:
"hello " + "world"
[31]:
'hello world'

Note that when we concatenate a string and a number, Python gets angry:

"hello " + 5
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-38-e219e8205f7d> in <module>()
----> 1 "hello " + 5

TypeError: Can't convert 'int' object to str implicitly

This happens because PYthon wants us to explicitly convert the number 5 into a string. It will also similarly complain about other data types. So, whenever you concatenate objects which are not strings, to avoid problems you can enclose the object to convert within an str function call like here:

[32]:
"hello " + str(7)
[32]:
'hello 7'

An alternative and faster way is by using the formatting percentage operator %, which substitutes the occurrences of the placeholder %s with whatever you place after the string:

[33]:
"hello %s" % 7
[33]:
'hello 7'

Even better, the %s can stay withing the string and be repeated. For each occurrence you can pass a different object to substitute, like for example in the tuple ("nice", "Python") (a tuple is simply an immutable sequence of elements separated by commas within round parenthesis).

[34]:
"It's so %s I'm finally learning %s" % ("nice", "Python")
[34]:
"It's so nice I'm finally learning Python"

✪ EXERCISE: the placeholder %s works with strings as well as any other data type, for example intergers. Write below here the command above, placing a %s at the end of the string, and adding at the tuple’s end the number 3 (separated by a comma).

Question: Can you place many %s one after another without spaces? Try.

[35]:
# write here

Using object methods¶

Almost everything in Python is an object, here we make a rapid introduction to just give an idea.

References

Almost everything in Python is an object. For example, the strings are objects. Every object type has actions called methods we can execute on that object. For example, we might want strings which represent names to have the first letter as capitalized: we can try finding a string method that already performs this action. Let’s try the existing method "capitalize()" on the string "trento" (note the string is all lowercase.):

[36]:
"trento".capitalize()
[36]:
'Trento'

Python just did the courtesy of upcasing the first letter.

✪ EXERCISE: Write in the cell below "trento". and press TAB: Jupyter should show the available methods for the string. Try the methods upper() and count("t")

[37]:
# write here

Liste - list¶

A list in Python is a sequence of elements of possibly different types, into which we can place any element we want.

References:

Let’s create a list of strings:

[38]:
x = ["hello", "soft", "python"]
[39]:
x
[39]:
['hello', 'soft', 'python']

Lists are sequences of possibly heterogenous elements, so inside you can place anything, integers, strings, dictionaries …:

[40]:
x = ["hello", 123, {"a":"b"}]
[41]:
x
[41]:
['hello', 123, {'a': 'b'}]

To access a particular element in a list, you can use an index among square brackets to denote the position:

[42]:
# first element

x[0]
[42]:
'hello'
[43]:
# second element

x[1]
[43]:
123
[44]:
# third element

x[2]
[44]:
{'a': 'b'}

In a list we can change the elements by assignment:

[45]:
# We change the *second* element:

x[1] = "soft"
[46]:
x
[46]:
['hello', 'soft', {'a': 'b'}]
[47]:
x[2] = "python"
[48]:
x
[48]:
['hello', 'soft', 'python']

To obtain the list length, we can use len:

[49]:
x = ["hello", "soft", "python"]

len(x)
[49]:
3

✪ EXERCISE: try accessing an element outside the list, and see what happens.

• is x[3] inside or outside the list?

• Is there some list x by which we can write x[len(x)] without problems?

• if you use negative indexes, what happens? Try -1, -2, -3, -4 …

[50]:
# write here

We can add elements to the end of the list by using the method append:

[51]:
x = []
[52]:
x
[52]:
[]
[53]:
x.append("hello")
[54]:
x
[54]:
['hello']
[55]:
x.append("soft")
[56]:
x
[56]:
['hello', 'soft']
[57]:
x.append("python")
[58]:
x
[58]:
['hello', 'soft', 'python']

Ordering lists¶

We can comfortably sort lists with the method .sort, which works on all the sortable objects. For example, we can order numbers:

IMPORTANT: .sort() modifies the list on which it is called, it doesn’t generate a new one!

[59]:
x = [ 8, 2, 4]

x.sort()
[60]:
x
[60]:
[2, 4, 8]

As another example, we can order strings:

[61]:
x = ['python', 'world', 'hello']

x.sort()
x
[61]:
['hello', 'python', 'world']

If we don’t want to modify the original list and we want to generate a new one instead, we can use the function sorted(). NOTE: sorted is a function, not a method:

[62]:
x = ['python', 'world', 'hello']

sorted(x)
[62]:
['hello', 'python', 'world']
[63]:
# original x was not changed:
x
[63]:
['python', 'world', 'hello']

✪ EXERCISE: What happens if you order strings which contain the same characters but uppercase instead of lowercase? How are they sorted? Do some test.

[64]:
# write here

✪ EXERCISE: What happens if in the same list you place both string and numbers, and try to sort it? Do some test.

[65]:
# write here

Reversed order

Suppose we want to sort the list in reversed order by using sorted function. To do so we can tell Python the boolean parameter reverse and its value, which in this case will be True. In other words, Python allows to specify optional parameters by name:

[66]:
sorted(['mondo', 'python', 'ciao'], reverse=True)
[66]:
['python', 'mondo', 'ciao']

✪ EXERCISE: To find info about sorted function, we could have asked some help to Python. To do so Python provides a handy function called help, which you could use like so help(sorted). Try executing it in the cell below. Sometimes the help can be quite complex, and it is upon us to find the interesting parameters.

[67]:
# write here

Reverse unordered lists

What if we wanted to reverse a list as it is, without any sorting, for example to pass from [6,2,4] to [2,4,6]? By searching the Python library, we can see there is a handy function reversed() which takes as parameter the list we want to reverse and generates a new reversed one.

✪ EXERCISE: Try executing reversed([6,2,4]) in the cell below, and see the result. Is it what you expect? In general, and especially in Python 3, whenever we expect a list and instead we get an object called iterator, we can solve the issue by passing the result to the function list()

[68]:
# write here the code

Dictionaries - dict¶

Dictionaries are containers which allow us to associate so-called keys to values. We will make a brief example to give the idea.

References:

We can create a dictionary with curly brackets { }, separating the keys from values with a colon :, and separating associations with the comma ,:

[69]:
d = {  'key 1':'value 1',
'key 2':'value 2'}

To access values, we can use keys among square brackets:

[70]:
d['key 1']
[70]:
'value 1'
[71]:
d['key 2']
[71]:
'value 2'

Values: dictionaries can hold whatever we want as values: numbers, strings, tuples, lists, other dictionaries ..

[72]:
d['key 3'] = 123
[73]:
d
[73]:
{'key 1': 'value 1', 'key 2': 'value 2', 'key 3': 123}
[74]:
d['key 4'] = ('I','am', 'a', 'tuple')
[75]:
d
[75]:
{'key 1': 'value 1',
'key 2': 'value 2',
'key 3': 123,
'key 4': ('I', 'am', 'a', 'tuple')}

✪ EXERCISE: try inserting into the dictionary some key/value couples with strings as keys and as values other lists and dictionaries

[76]:
# write here:

Keys: Keys have the important restriction: they must be an immutable type. We’ve already put strings so we know they must be immutable. Numbers also are immutable:

[77]:
d[123] = 'value 3'
[78]:
d
[78]:
{'key 1': 'value 1',
'key 2': 'value 2',
'key 3': 123,
'key 4': ('I', 'am', 'a', 'tuple'),
123: 'value 3'}

Tuples are an immutable sequence so we can use them as keys:

[79]:
d[('I','am','a','tuple')] = 'value 4'
[80]:
d
[80]:
{'key 1': 'value 1',
'key 2': 'value 2',
'key 3': 123,
'key 4': ('I', 'am', 'a', 'tuple'),
123: 'value 3',
('I', 'am', 'a', 'tuple'): 'value 4'}

WARNING: Not all types are viable as keys. Without going into details, in general you cannot insert into dictionaries as keys types which can be modified after they were created.

✪ EXERCISE:

• Try inserting in a dictionary a list like ['a','b'] as key, and put any value you like as value. Python should complain, and you should see the writing TypeError: unhashable type: 'list'

• try also to insert a dictionary as key (for example the empty dictionary {}). Which result do you obtain?

[81]:
# write here the code

Visualizing execution with Python Tutor¶

We’ve seen the main data types. Before going on, let’s discover the best tools to understand what happens when we execute code. Python tutor is a very good website to visualize Python code execution, which allows to progress forward and even backwards in the code execution. Take advantage of it as much as you can, it should work with most code you will see in the book. Let’s see some example.

Python tutor 1/4

Go to the website pythontutor.com and select Python 3

Python tutor 2/4

Make sure at least Python 3.6 is selected:

Python tutor 3/4

Try inserting:

x = 5
y = 7
z = x + y

Python tutor 4/4

By clicking on Next, you will see the changes in Python memory

Debugging code in Jupyter¶

Python Tutor is fantastic, but when you execute code in Jupyter and it doesn’t work, what can you do? To inspect the execution, the editor usually makes available a tool called debugger, which allows to execute instructions one by one. At present (August 2018), the Jupyter debugger is called pdb and it is extremely limited. To overcome its limitations, in this book we invented a custom solution based on Python Tutor.

If you insert Python code in a cell, and then at the cell end you write the instruction jupman.pytut(), the preceding code will be visualized inside Jupyter notebook with Python Tutor, as if by magic.

WARNING: jupman is a collection of support functions we created just for this book.

Whenever you see commands which start with jupman, to make them work you need first to execute the cell at the beginning of the document. For convenience we report here that cell. If you already didn’t, execute it now.

[82]:
# Remember to execute this cell with Control+Enter
# These commands tell Python where to find the file jupman.py
import jupman;

Now we are ready yo try Python Tutor with the magic function jupman.pytut():

[83]:
x = 5
y = 7
z = x + y

jupman.pytut()
[83]:

Python Tutor : Limitation 1¶

Python Tutor is handy, but there are important limitations:

ATTENTION: Python Tutor only looks inside one cell!

Whenever you use Python Tutor inside Jupyter, the only code Python tutors considers is the one inside the cell containing the command jupman.pytut()

So for example in the two following cells, only print(w) will appear inside Python tutor without the w = 3. If you try clicking Forward in Python tutor, you will we warned that w was not defined.

[84]:
w = 3
[85]:
print(w)

jupman.pytut()
3
Traceback (most recent call last):
File "../jupman.py", line 2340, in _runscript
self.run(script_str, user_globals, user_globals)
File "/usr/lib/python3.7/bdb.py", line 578, in run
exec(cmd, globals, locals)
File "<string>", line 2, in <module>
NameError: name 'w' is not defined
[85]:

To have it work in Python Tutor you must put ALL the code in the SAME cell:

[86]:
w = 3
print(w)

jupman.pytut()
3
[86]:

Python Tutor : Limitation 2¶

WARNING: Python Tutor only uses functions from standard Python distribution

Python Tutor is good to inspect simple algorithms with basic Python functions, if you use libraries from third parties it will not work.

If you use some library like numpy, you can try only online to select Python 3.6 with Anaconda :

Iteration¶

You will often need to perform actions on every element of a sequence.

References

For loops

Among the various ways to do it, there is the so called for loop:

[87]:
animals = ['dogs', 'cats', 'squirrels', 'elks']

for animal in animals:
print("In the list there are:")
print(animal)
In the list there are:
dogs
In the list there are:
cats
In the list there are:
squirrels
In the list there are:
elks

Here we defined the variable animal (we could have called it with any name, also foo). For every element in the list animals, all the instructions in the block are executed. Everytime they are executed, the variable animal becomes one of the values from the list animals

WARNING 1: REMEMBER THE TWO DOTS : AT THE END OF THE for LINE !!!

WARNING 2: ALWAYS use sequences of 4 white spaces to indent the code

Sequences of only 2 spaces are still allowed but not recommended.

WARNING 3: TAB behavior may vary depending on your editor.

According to the editor you are using, by hitting TAB you could obtain a sequence of white spaces (i.e. the recommended 4 spaces as it happens in Jupyter), or a special character of tabulation (to avoid)! As much as boring this distinction might look to you, please remember it because it might generate errors very difficult to spot.

[88]:
# Let's see what happens with Python tutor:

animals = ['dogs', 'cats', 'squirrels', 'elks']

for animal in animals:
print("In the list there are:")
print(animal)

jupman.pytut()
In the list there are:
dogs
In the list there are:
cats
In the list there are:
squirrels
In the list there are:
elks
[88]:

✪ EXERCISE: Let’s try to understand all the warnings above a bit better. Write down here the previous for with the animals (no copy and paste!), try if it works. Remember to use 4 spaces for the indentation.

• Try removing the colon at the end and check the error given by Python

• re-add the colon, and try now varying the indentation. Try placing two spaces at the beginning of both prints, check if it works

• try now placing two spaces before the first print and 4 spaces before the second, check if it executes

[89]:
# write here - copy the above for

for in range¶

Another very common iteration is incrementing a counter at each cycle. Compared to other languages, Python offers a peculiar system based on the function range(n), which returns a sequence with the first numbers from 0 included to n excluded. We can use it like this:

[90]:
for index in range(3):
print(index)
0
1
2
[91]:
for index in range(6):
print(index)
0
1
2
3
4
5

Let’s have a better look with Python tutor:

[92]:
for index in range(6):
print(index)

jupman.pytut()
0
1
2
3
4
5
[92]:

As an alternative to list our animals, we can use this style like so:

[93]:
animals = ['dogs', 'cats', 'squirrels', 'elks']

for index in range(3):
print("In the list there are:")
print(animals[index])
In the list there are:
dogs
In the list there are:
cats
In the list there are:
squirrels

Let’s have a better look with Python tutor:

[94]:
animals = ['dogs', 'cats', 'squirrels', 'elks']

for index in range(3):
print("In the list there are:")
print(animals[index])

jupman.pytut()
In the list there are:
dogs
In the list there are:
cats
In the list there are:
squirrels
[94]:

Functions¶

A function takes some parameters and uses them to produce or report some result.

References

To define a function, we can use the keyword def:

[95]:
def my_print(x,y):   # REMEMBER THE COLON AT THE END OF THE ROW !!!
print('We will now print the sum of two numbers')
print('The sum is %s' % (x + y))

We can call the function like this:

[96]:
my_print(3,5)
We will now print the sum of two numbers
The sum is 8

Let’s have a better look with Python Tutor:

[97]:
def my_print(x,y):   # REMEMBER THE COLON AT THE END OF THE ROW !!!
print('We will now print the sum of two numbers')
print('The sum is %s' % (x + y))

my_print(3,5)

jupman.pytut()
We will now print the sum of two numbers
The sum is 8
[97]:

The function we just declared prints some values, but returns nothing. To have a function which actually retuns a value, we must use the keyword return.

[98]:
def my_sum(x,y):
s = x + y
return s
[99]:
my_sum(3,5)
[99]:
8
[100]:
# Let's have a better look with Python Tutor:

def my_sum(x,y):
s = x + y
return s

print(my_sum(3,5))

jupman.pytut()
8
[100]:

✪ EXERCISE: If we try to assign to a variable x the return value of the function my_print which apparently returns nothing, what value will go into x? Try to understand it down here:

[101]:
# write here

✪ EXERCISE: Write down here a function average which calculates and return the average of two input numbers x and y.

Show solution
[102]:
# write here

✪✪ EXERCISE: Write down here a function called startb which takes a string x as input. If the string begins with the letter 'b', for example 'bank' the function prints the writing bank begins with b, otherwise prints it doesn’t.

• To check whether the first character equals 'b', use the operator == (WARNING: it’s DOUBLE equal!)

• Do you envisage any problem if the string is empty? How could you solve them? (to separate more conditions in the if, use either the and / or operators according to the way you built the if).

Show solution
[103]:
# write here

bank starts with b

Lambda functions¶

Python allows a variable to contain a function. For example, we know that len("ciao") gives us the length of the string "ciao"

[104]:
len("ciao")
[104]:
4

Let’s try creating a variable my_variable which points to the function len.

[105]:
my_variable = len

NOTE: we didn’t add parameters to len!

Now we can use my_variable exactly like we use the function len, which gives us the length of sequences like strings:

[106]:
my_variable("ciao")
[106]:
4

We can also reassign my_variable to other functions, for example sorted. Let’s see what happens:

[107]:
my_variable = sorted

by calling my_variable, we expect to see the characters of "ciao" in alphabetical order:

[108]:
my_variable("ciao")
[108]:
['a', 'c', 'i', 'o']

In Python we can define functions in one row with the so-called lambda functions:

[109]:
my_f = lambda x: x + 1

What is the my_f ? It takes a parameter x and returns the result of calculating the expression x + 1:

[110]:
my_f(5)
[110]:
6

We can also pass two parameters:

[111]:
my_sum = lambda x,y: x + y
[112]:
my_sum(3,5)
[112]:
8

✪ EXERCISE: try defining down here a lambda function to calculate the average between two numbers x and y, and assign it to the function average

Show solution
[113]:

# write here

List transformations¶

References:

Let’s say we want to take the animals list and generate a new one in which all the names start with a a capitalized character. As a matter of fact, we are creating a new list by operating a transformation on the previous one. There exist several ways to achieve this goal, the simplest being a for cycle like the following.

Trasfomations with a for¶

[114]:
animals = ['dogs', 'cats', 'squirrels', 'elks']

new_list = [] # at every cycle the variable 'animal' contains a name taken from the list 'animals'
for animal in animals:
new_list.append(animal.capitalize())   # we add the current animal name to the new list,
# with the first letter uppercased
new_list

#let's see what happens in Python Tutor
jupman.pytut()
[114]:

Important note: strings methods never modify the original string, they always generate a new string. So the original list animals will still contain the original strings without modifications:

[115]:
animals
[115]:
['dogs', 'cats', 'squirrels', 'elks']

✪ EXERCISE: Try writing down here a for loop (no copy and paste!) to parse the list of animal names and create another list we will call m, in which all the characters of animals names are uppercase (use .upper() method)

Show solution
[116]:
animals = ['dogs', 'cats', 'squirrels', 'elks']

# write here

[116]:
['DOGS', 'CATS', 'SQUIRRELS', 'ELKS']

Transformations with list comprehensions¶

References: SoftPython - Sequences

The same identical above transformation could be performed with a so-called list comprehension, which allows to generate new lists by executing the same operation on all the elements of an existing starting list. The syntax is similar to lists, in fact they start and end with square brackets, but inside you will find a special for to cycle through the sequence:

[117]:
animals = ['dogs', 'cats', 'squirrels', 'elks']

new_list = [animal.capitalize() for animal in animals]
[118]:
new_list
[118]:
['Dogs', 'Cats', 'Squirrels', 'Elks']

Let’s see what happens with Python Tutor:

[119]:
animals = ['dogs', 'cats', 'squirrel', 'elks']

new_list = [animal.capitalize() for animal in animals]

jupman.pytut()
[119]:

✪ EXERCISE: Try using a list comprehension to place all the characters as uppercase

Show solution
[120]:

animals = ['dogs', 'cats', 'squirrels', 'elks']

# write here

Filtering with comprehensions:

If we want, we can also filter data by using a special if placed at the end of the comprehension. For example, we could select only the animals having a name length of 4 characters:

[121]:
[animal.upper() for animal in animals if len(animal) == 4]
[121]:
['DOGS', 'CATS', 'ELKS']

Transformations with map¶

Yet another way to transform a list into a new one is by using the operation map, which given a list, generates another one by applying a function f we pass as parameter to each element of the original list. For example, to solve the same previous exercise we could create on the fly a function f with a lambda which places the first letter of a string as uppercase, then we could call map and pass the function we’ve just created:

[122]:
animals = ['dogs', 'cats', 'squirrels', 'elks']

f = lambda animal: animal.capitalize()

map(f, animals)
[122]:
<map at 0x7f0c7813ab50>

Sadly, the result is not yet what we wanted. The problem is Python 3 awaits to return a real list, preferring instead to give us an iterator. How comes? For efficiency reasons, Python 3 hopes we will never actually use any element from the new sequence, which would spare it the need to compute the function on all the elements of the original list.

We can force it to actually materialize a list by using the function list:

[123]:
animals = ['dogs', 'cats', 'squirrels', 'elks']

f = lambda animal: animal.capitalize()

list(map(f, animals))
[123]:
['Dogs', 'Cats', 'Squirrels', 'Elks']

To get a completely equivalent example, we can assign the result to new_list:

[124]:
animals = ['dogs', 'cats', 'squirrels', 'elks']

f = lambda animal: animal.capitalize()

new_list = list(map(f, animals))
[125]:
new_list
[125]:
['Dogs', 'Cats', 'Squirrels', 'Elks']

A true Python hacker will probably prefer writing everything in one line, like this:

[126]:
animals = ['dogs', 'cats', 'squirrels', 'elks']

new_list = list(map(lambda animal: animal.capitalize(), animals))
[127]:
new_list
[127]:
['Dogs', 'Cats', 'Squirrels', 'Elks']

✪ EXERCISE: Was the original list animals changed? Check it.

✪ EXERCISE: Given a list numbers = [3, 5, 2, 7] try writing a map which generates a new list with the numbers doubled, like [6, 10, 4, 14]:

Show solution
[128]:

numbers = [3, 5, 2, 7]

# write here

Matrices¶

Once we’re done with the presentation, it’s time to put some more effort. Let’s briefly see lists of lists, for more details check the references.

References:

✪✪ EXERCISE: Given two lists with animal names and the corresponding life expectancy in years:

animals = ['dog', 'cat', 'pelican', 'squirrel', 'eagle']
years = [12,14,30,6,25]

write in the cell below some code to generate a list of lists of two elements, like so:

[
['dog', 12],
['cat', 14],
['pelican', 30],
['squirrel', 6],
['eagle', 25]
]
Show solution
[129]:

animals = ['dog', 'cat', 'pelican', 'squirrel', 'eagle']
years = [12,14,30,6,25]

# write here

✪✪ EXERCISE modify the code of previous exercise with a regular for loop to filter only the species with life expectancy above 13 years, so to obtain this result:

[['cat', 14], ['pelican', 30], ['eagle', 25]]
Show solution
[130]:

animals = ['dog', 'cat', 'pelican', 'squirrel', 'eagle']
years = [12,14,30,6,25]

# write here

EXERCISE: Write down here some code with a regular for loop so to filter only the species with life expectancy above 10 years and below 27, so to obtain this result:

[['dog', 12], ['cat', 14], ['eagle', 25]]
Show solution
[131]:

animals = ['dog', 'cat', 'pelican', 'squirrel', 'eagle']
years = [12,14,30,6,25]

# write here

Zip function¶

The zip function takes two lists and produces a new sequence, in which places couples of elements as tuples (we recall tuples are immutable sequences), coupling the first element from the first list with the first element from the second list, and so on and so forth:

[132]:
list(zip(['a','b','c'], [5,2,7]))
[132]:
[('a', 5), ('b', 2), ('c', 7)]

Why did we place also list in the example? Because zip has the same problem of map: it doesn’t materialize a list right away as maybe we would like:

[133]:
zip(['a','b','c'], [5,2,7])
[133]:
<zip at 0x7f0c781579b0>

✪✪✪ EXERCISE: As you see with the zip we can obtain a result similar to that of previous exercise, but here we have tuples with round parenthesis instead of square brackets. Can you obtain the same identical result with a list comprehension or a map (without filtering, for now)?

• to convert a tuple into a list use the function list:

[134]:
list(  ('hello', 'soft', 'python')  )  # we placed inside a tuple delimited by round brackets
[134]:
['hello', 'soft', 'python']
Show solution
[135]:

animals = ['dog', 'cat', 'pelican', 'squirrel', 'eagle']
years = [12,14,30,6,25]

# write here - solution with list comprehension

Show solution
[136]:

animals = ['dog', 'cat', 'pelican', 'squirrel', 'eagle']
years = [12,14,30,6,25]

# write here - solution with map

✪✪✪ EXERCISE: carry out the previous exercise by filtering the animals with life expectancy above 13 years, using zip and a list comprehension

Show solution
[137]:

animals = ['dog', 'cat', 'pelican', 'squirrel', 'eagle']
years = [12,14,30,6,25]

# write here

✪✪ EXERCISE: Given the two lists with animal names and the corresponding life expectancy as above, write in the cell below some code that with a regular for cycle generates a dictionary which associates each species to its life expectancy, like so:

{
'dog': 12,
'cat': 14,
'pelican': 30,
'squirrel': 6,
'eagle': 25
}

WARNING: order doesn’t matter

According the the exact Python version you have and how the dictionary is created, the fields order might differ from the example when printed. This is totally normal, as dictionary keys can be seen as members of a set without any particular order.

If you want to be sure about printing keys in the same insertion order, you have to use an OrderedDict

Show solution
[138]:

animals = ['dog', 'cat', 'pelican', 'squirrel', 'eagle']
years = [12,14,30,6,25]

# write here

To obtain the same result in only one line, it’s possible to use the function zip as done in previous exercises, and than the function dict to create a dictionary starting from the list of element couples generated by the zip:

[139]:
dict(zip(animals, years))
[139]:
{'dog': 12, 'cat': 14, 'pelican': 30, 'squirrel': 6, 'eagle': 25}

✪✪ EXERCISE: Given a list of products containing lists each with a category, brand and quantity of sold packages:

sales = [
['tomatoes', 'Santini', 5],
['tomatoes', 'Cirio', 1],
['tomatoes', 'Mutti', 2],
['cereals', 'Kelloggs', 3],
['cereals', 'Choco Pops', 8],
['chocolate','Novi', 9],
['chocolate','Milka', 4],
]

Write some Python code in the cell below to create a dictionary in which the keys are the categories and values are the sum of sold packages for that category, like so:

{
'tomatoes': 8,
'cereals': 11,
'chocolate': 13
}
• USE regular for cycle

• HINT: pay attention to the two cases, when the dictionary to create still doesn’t hold the category extracted from the current list under examination, and when it already contains it.

Show solution
[140]:

sales = [
['tomatoes', 'Santini', 5],
['tomatoes', 'Cirio', 1],
['tomatoes', 'Mutti', 2],
['cereals', 'Kelloggs', 3],
['cereals', 'Choco Pops', 8],
['chocolate','Novi', 9],
['chocolate','Milka', 4],
]

# write here