Tutorial 1: Functions and branching
Objectives
The course material we will practice today: Writing
simple functions with def
, branching with
if
.
Setup: before you start
Launching Spyder
We will be writing our programs using the Spyder programming environment. This is the Python programming environment that we recommend for this course (though the programs you write will run on any Python platform).
Where can you get it?
- If you are using a computer lab machine, everything here is already set up for you; all you need is your polytechnique LDAP username and password, which are the same as what you use for your polytechnique email. You are allowed to use the computer lab machines at any time, provided the room is not being used for another course. Remember: wear a mask, maintain a distance, and use the hydroalcoholic gel available there before touching the machines.
- If your are using your own computer, you will probably need to install Spyder first; Instructions for installing Spyder (via anaconda) are on the CSE101 moodle page.
To launch Spyder,
- Click on the Applications menu
- Click on the Programming menu
- Click Spyder3.
- If you see a “Spyder update” message, just click OK and ignore it.
Create a new project
Before you start: create a new project, called Tutorial_1. This can be done as follows:
- Click on
Projects
(n the top menu of Spyder), - then select
New Project...
. - Make sure
New Directory
is checked. - Enter
Tutorial_1
in the box next toProject name
, and clickCreate
. - Make sure you see
Tutorial_1
appear in the left-most window pane of Spyder.
This will ensure that files from this week and future weeks do not get mixed up together.
Exercises
Each of the tutorials in CSE101 is a collection of programming exercises. You can upload them (via the upload forms below) to the server for autograding. You are free to do this as many times as you wish, so we strongly encourage you to upload your file after completing each exercise so that we can see your progress.
The version of your code which will be used for grading a tutorial is the last version you submit before 23:59 on Monday of the week following the tutorial (for example, your solutions for this tutorial must be submitted before 23:59 October 2).
Now create a new program file called dates.py. Warning: make sure you get the filename right, or the submission form will not accept it!
At the top of each of the Python source files generated by Spyder, we see something similar to
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Sep 28 10:58:13 2023
@author: firstname.lastname
"""
- The first line (
#!/usr/bin/env python3
)is a special kind of comment that will allow this program to be run as a script from the command-line on Unix or Linux systems. - The second line (
# -*- coding: utf-8 -*-
) is another special kind of comment. This one tells Python what sort of text encoding we are using:utf-8
allows us to use accents (and other international characters) if we wish. - The next few lines, between the triple-quotes
"""
, are what we call a docstring. Python can use this text to describe the program.
Exercise 0: Using the console
The goal of this exercise is to get used to the console in Spyder, and try out some basic operations. This exercise (unlike the rest) will not be submitted anywhere and graded.
Basic arithmetic
Go to the console (generally in the bottom right-hand corner of the Spyder window), and type the following at the prompt:
1]: a = 5 In [
This will create a variable, assign the integer value 5 to it, and
name the resulting variable a
. Technically, we say the
name a
is bound to the
value 5.
Now create an integer variable named b
with value
10.
Now type
3]: a + b In [
The console will evaluate this expression, and show the result (the
sum of the values referred to by a
and b
),
which should be 15:
3]: 15 Out[
(Notice the console starts this line with Out[n]:
to
indicate that this is the result of the expression entered at the prompt
In [n]:
).
Try some other arithmetic operations: a * b
,
a / b
, a // b
(integer division),
b % a
(computing the remainder). Make sure that all the
results make sense to you - and note the difference between the results
of a / b
and a // b
!
Strings
Another important data type for us will be string
. The
+
operation is also defined for strings: it computes the
concatenation of two strings strings. Try this:
4]: h = 'Hello '
In [
5]: w = 'world!'
In [
6]: h + w
In [7]: 'Hello world!' Out[
One can ask Python to try to convert a given value to an integer or
string type using the built-in functions int
and
str
, respectively. Try typing str(a) + str(b)
in the console, and explain the output. Will it be the same as for
str(b) + str(a)
or str(a + b)
?
Exercise 1: Getting started
To get used to the submission interface and discuss basic things about functions, let us look at this:
def hello_world():
"""
This function simply returns the string 'Hello world!'
"""
return 'Hello world!'
Here you see
- the function definition
def hello_world():
, wherehello_world
is the function name - the docstring, surrounded by triple-quotes
(
"""
); the docstring explains what the function does - the body of the function, consisting only of a return statement
Add this function to dates.py
. Now save
dates.py, and click on the triangular “play” icon to make
Python load and run your new program.
Testing
Now you should be able to test your code by doing this in the console:
8]: hello_world()
In [8]: 'Hello world!' Out[
Upload your solution to the form below, it will be tested automatically.
Caveat emptor: return vs print
Caveat. There is an important difference between
return
and print
. Consider the following
function
def hello_world2():
"""
Prints 'Hello world!'
"""
print('Hello world!')
Calling it, you will see
9]: hello_world2()
In [! Hello world
Notice that
- There are no quotation marks: the content of the string appears directly in the console.
- There is no
Out[9]:
before the string! The string has been displayed on the console, but it is not treated as a “result” or “return value” of thehello_world2
function.
These two functions will behave very differently if you will try to use their return values in the further computation:
10]: a = hello_world()
In [
11]: a
In [11]: 'Hello world!'
Out[
12]: print(a)
In [!
Hello world
13]: b = hello_world2()
In [!
Hello world
14]: print(b)
In [None
Recall that None
is Python’s special object that
represents “nothing”. This is the default result for functions that do
not explicitly return
anything.
Exercise 2: To work or not to work?
In this exercise, we will check whether a day of the week is a workday or a holiday.
Complete the following function
check_day
and add it to dates.py
:
def check_day(n):
"""
Given an integer between 1 and 7 inclusive,
return either string 'work!' or string 'rest!'
depending on whether the day is a workday or not
"""
if n < 1 or n > 7:
return None # invalid m
pass # remove this line and replace it with your code
Hint: you will have to use an if
statement (actually, only one!).
Testing
Now test your code. You should be able to reproduce the following behaviour in the console:
15]: check_day(1)
In [15]: 'work!'
Out[
16]: check_day(7)
In [16]: 'rest!' Out[
Upload your solution using the form below for further, automatic testing.
Exercise 3: The months of the year
In this exercise, we will write a function that takes the number
corresponding to a month (like 1 for January, 9 for September, or 10 for
October), and returns the name of the month (as a
string
).
Complete the following function
name_of_month
, and add it to dates.py
:
def name_of_month(m):
"""Given an integer m between 1 and 12 inclusive,
indicating a month of the year, returns the name of that month.
For example: name_of_month(1) == 'January' and name_of_month(12) == 'December'.
If the month does not exist (that is, if m is outside the legal range),
then this function returns None.
"""
if m < 1 or m > 12: # Non-existent month
return None
pass # remove this line and replace it with your code to compute month names
Hints:
- You will need to use a series of
if
,elif
, andelse
statements (with multipleelif
s). - Be careful with the spelling of the month names! And make sure that
the first letter of each name is a capital letter, with the others in
lower case (that is: we want
'December'
, not'DECEMBER'
or'december'
).
Testing
Now test your code by doing this in the console
(after re-running dates.py
):
17]: name_of_month(1)
In [17]: 'January'
Out[
18]: name_of_month(8)
In [18]: 'August' Out[
Check the capitalization of your month names carefully!
Once you have done this, upload your solution using the form below for automatic testing.
Exercise 4: From numbers to words
When you are counting items in a sequence, like days of a month, you say the 1st, 2nd, 3rd, 4th, 5th, …
Complete the following function
str_with_suffix
, and add it to dates.py
:
def str_with_suffix(n):
"""Convert the integer n to a string expressing the corresponding
position in an ordered sequence.
Eg. 1 becomes '1st', 2 becomes '2nd', etc.
"""
pass # remove this line and replace with your code
For example:
str_with_suffix(1)
should return'1st'
;str_with_suffix(2)
should return'2nd'
;str_with_suffix(3)
should return'3rd'
;str_with_suffix(4)
should return'4th'
;str_with_suffix(11)
should return'11th'
;str_with_suffix(21)
should return'21st'
;str_with_suffix(32)
should return'32nd'
;str_with_suffix(43)
should return'43rd'
.
By convention, we say str_with_suffix(0)
is
'0th'
.
Hints:
- Use
str
to convert integers to strings. - Use
+
to join strings together. - The possible suffixes are
'st'
,'nd'
,'rd'
, and'th'
. - If you want to get the last digit (in base ten) of an integer, use
% 10
. - Be careful of numbers ending in 11, 12, and 13!
Testing
Test your code using the examples above in the
console (after re-running dates.py
).
Upload your solution to the form below, it will be tested automatically.
Exercise 5: Leap years
A leap year is a year with 366 days (including a 29th of February) instead of the usual 365. Here are the rules (for the standard Gregorian calendar):
- Every year that is exactly divisible by four is a leap year,
- except for years that are exactly divisible by 100,
- unless they are exactly divisible by 400 (in which case they are leap years).
The definition might seem a bit tricky, but for example:
- 1900 was not a leap year (divisible by 100)
- 2000 was a leap year (divisible by 400
- 2016 was a leap year (divisible by 4, but not 100)
- 2018 is not a leap year (not divisible by 4)
Define a new function is_leap_year
(in
dates.py
) that
- takes an integer
y
as an argument, and return
sTrue
if the yeary
is a leap year, andFalse
if not.
Here’s a start:
def is_leap_year(y):
""" Return True if y is a leap year, False otherwise. """
pass # remove this line and replace with your own code
Here’s what we expect to happen in the console, once you’ve run your code:
19]: is_leap_year(1800)
In [19]: False
Out[
20]: is_leap_year(2000)
In [20]: True
Out[
21]: is_leap_year(2012)
In [21]: True
Out[
22]: is_leap_year(2018)
In [22]: False Out[
Testing
Test your code using the examples above in the
console (after re-running dates.py
). Make sure you get the
expected answer in each case!
Upload your solution using the form below. It will be tested automatically.
Exercise 6: How many days in a month?
Now we want a function that tells us the number of days in a given month of a given year. Recall that
- January, March, May, July, August, October, and December all have 31 days in any given year;
- April, June, September, and November all have 30 days in any given year;
- February has 28 days most of the time, but 29 days in a leap year.
Define a new function number_of_days
(in dates.py
) that
- takes integers
m
andy
as arguments (indicating the number of the month and year), and return
s the number of days in that month.
Make sure to use your is_leap_year
function to check
what to return when m == 2
!
Here’s a start:
def number_of_days(m, y):
"""Returns the number of days in month m of year y."""
pass # remove this line and replace with your own code
Testing
Here’s what we expect to happen in the console, once you’ve run your code:
23]: number_of_days(9, 2018)
In [23]: 30
Out[
24]: number_of_days(3, 2018)
In [24]: 31
Out[
25]: number_of_days(2, 2018)
In [25]: 28
Out[
26]: number_of_days(2, 2000)
In [26]: 29 Out[
Test your code using these examples - and think of some new tests for yourself (like today’s month, for example, and February of this year).
Upload your solution to the form below. It will be tested automatically.
Exercise 7: Constructing dates
Define a function date_string
which
takes three integer arguments, d
, m
, and
y
representing the day, month, and year, and returns a
string expressing the date in words, in the following format:
'The D of M, Y'
where
- D is
d
followed by itssuffix
(as in Exercise 2) - M is
'January'
ifm
is 1,'February'
ifm
is 2, … - Y is just
y
.
If the date given does not exist (eg. the 32nd of January, 1970, or
the 29th of February, 1900) then return the string
'Nonexistent date'
. (You should use your
number_of_days
function to help check this). You should use
your str_with_suffix
function to treat the day argument
d
, and your name_of_month
function to treat
the month argument m
. If name_of_month
returns
None
, then the month was illegal and you can return
'Nonexistent date'
.
Here is a table of sample inputs and expected arguments:
date_string(28, 9, 2017)
should return'The 28th of September, 2017'
date_string(31, 12, 1999)
should return'The 31st of December, 1999'
date_string(2, 3, 786)
should return'The 2nd of March, 786'
date_string(29, 2, 2000)
should return'The 29th of February, 2000'
date_string(29, 2, 1800)
should return'Nonexistent date'
date_string(33, 1, 1979)
should return'Nonexistent date'
date_string(12, 0, 105)
should return'Nonexistent date'
Don’t forget to include a useful docstring at the top of your function!
Testing
Make sure you test your function - it should correctly reproduce the seven examples above.
Then, upload your solution to the form below, for further automated testing.
Exercise 8: Breaking down times
Everybody knows that there are sixty seconds in a minute, sixty minutes in an hour, and 24 hours in a day.
Define a new function time_string
which
takes a number of seconds n
as an argument, and returns a
string describing the corresponding number of days, hours, minutes, and
seconds. time_string
always includes a number of seconds in
its output (even if 0), but ‘0 days’, ‘0 hours’, and ‘0 minutes’ are
always omitted.
We expect the following outputs:
time_string(0)
returns'0 seconds'
time_string(1)
returns'1 second'
time_string(10)
returns'10 seconds'
time_string(100)
returns'1 minute, 40 seconds'
time_string(1000)
returns'16 minutes, 40 seconds'
time_string(10000)
returns'2 hours, 46 minutes, 40 seconds'
time_string(1000000)
returns'11 days, 13 hours, 46 minutes, 40 seconds'
time_string(100000000)
returns'1157 days, 9 hours, 46 minutes, 40 seconds'
Don’t forget to include a useful docstring at the top of your function!
Testing
Test your code in the console using the eight
examples above (after re-running dates.py
). Make sure the
outputs are all correct. Be careful with spaces and punctuation!
Upload your solution to the form below, it will be tested automatically.