Quick introduction to Python
Download exercises zip
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 commandpython3
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 hitShift+Enter
. What happens to the cursor? Try the differences withControl+Enter
. If you don’t understand the difference, try hittingShift+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 |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 ,
In Python and in many data formats, you always have to use the English 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
had breakfast
didn't clean teeth
CAN'T exit home
False
True
False
False
didn't have breakfast
CAN'T exit home
True
True
had breakfast cleaned teeth done everything ! can exit home !
[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]:
had_breakfast = False
if not had_breakfast:
print("I'm hungry !")
else:
print("the cereals were so good")
I'm hungry !
[22]:
had_breakfast = True
if not had_breakfast:
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
[23]:
have_life_jacket = True
had_breakfast = 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?
[30]:
# write here the if
Strings - str
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
Lists - list
A list in Python is a mutable 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 writex[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 mutable 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 writingTypeError: 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 2453, 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']
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']
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.
[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 theand
/or
operators according to the way you built theif
).
[103]:
# write here
bank starts with b
volley doesn't start with b
doesn't start 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
[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)
[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 0x7fa0cc3a46d0>
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]
:
[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]
]
[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]]
[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]]
[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 0x7fa0cc377c30>
✪✪✪ 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']
[135]:
animals = ['dog', 'cat', 'pelican', 'squirrel', 'eagle']
years = [12,14,30,6,25]
# write here - solution with list comprehension
[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
[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
[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
cycleHINT: 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.
[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
Furhter readings
Tools and scripts: If you want execute code in editors other than Jupyter or you’re curious about Python architecture, we invite you to read Tools and scripts page.
Error handling and testing: To understand how to deal with error conditions you can look at the separate notebook Error handling and testing, it’s also useful to understand how to solve some exercises of Part A - Foundations
[ ]: