Session 2

Published

September 25, 2023

Topics Covered
  • Functions, methods & modules
  • Reading Files
  • The For loop
  • The if statement

Welcome Back

!figlet Welcome to Session 2
__        __   _                            _        
\ \      / /__| | ___ ___  _ __ ___   ___  | |_ ___  
 \ \ /\ / / _ \ |/ __/ _ \| '_ ` _ \ / _ \ | __/ _ \ 
  \ V  V /  __/ | (_| (_) | | | | | |  __/ | || (_) |
   \_/\_/ \___|_|\___\___/|_| |_| |_|\___|  \__\___/ 
                                                     
 ____                _               ____  
/ ___|  ___  ___ ___(_) ___  _ __   |___ \ 
\___ \ / _ \/ __/ __| |/ _ \| '_ \    __) |
 ___) |  __/\__ \__ \ | (_) | | | |  / __/ 
|____/ \___||___/___/_|\___/|_| |_| |_____|
                                           

Review of Last Session

Any questions?

A small problem.

%load_problem countdown
Problem: Countdown

Write a program countdown.py to print numbers from n to 1.

You can verify your solution using:

%verify_problem countdown

The program should take the number n as command-line argument.

$ python countdown.py 5
5
4
3
2
1
%%file countdown.py

print(1)

Writing countdown.py
!python countdown.py 5
%verify_problem countdown
ERROR: Unable to find program countdown.py.

Functions, Methods and Modules

Python has many built-in functions.

sum([1, 2, 3, 4, 5])
15
len("hello")
5
print("hello")
hello

Python doesn’t support operations on incompatible datatypes.

1 + "2"
TypeError: unsupported operand type(s) for +: 'int' and 'str'
1 + int("2")
3
str(1) + "2"
'12'
int("2")
2
str(1)
'1'

Example: counting the number of digits in a number

How to count the number of digits in a number?

12345
12345
2 ** 1000
10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376
number = 1234
number
1234
str(number)
'1234'
len(str(number))
4
len(str(2**1000))
302
len(str(2**10000))
3011

Writing our own functions

def square(x):
    return x*x
square(4)
16
def square(x):
    y = x*x
    return y
square(4)
16
%load_problem cube
Problem: Cube

Write a function cube to compute cube of a number.

>>> cube(2)
8

You can verify your solution using:

%verify_problem cube

# your code here


%verify_problem cube
ERROR: Unable to find function with name cube.

Functions are values too!

def square(x):
    return x*x
square(4)
16
square() # error
TypeError: square() missing 1 required positional argument: 'x'
square
<function __main__.square(x)>
x = 5
x
5
y = x
type(x)
int
square
<function __main__.square(x)>
type(square)
function
f = square
f
<function __main__.square(x)>
f(4)
16
def square(x):
    return x*x

def sum_of_squares(x, y):
    return square(x) + square(y)
sum_of_squares(3, 4)
25
def cube(x):
    return x*x*x

def sum_of_cubes(x, y):
    return cube(x) + cube(y)
sum_of_cubes(3, 4)
91
def sq1(x):
    return x*x

def sq2(y):
    return y*y

If you notice, the sum_of_squares and sum_of_cubes are almost the same.

Can we generalize these two functions into a single one?

def sumof(f, x, y):
    return f(x) + f(y)
sumof(square, 3, 4)
25
sumof(cube, 3, 4)
91
sumof(len, "hello", "python")
11
1 + 2
3
functions = [square, cube]
functions
[<function __main__.square(x)>, <function __main__.cube(x)>]
functions[0]
<function __main__.square(x)>
functions[0](4)
16

Passing functions as arguments is so useful that there are many built-in functions that accept functions as arguments.

max(3, 4)
4
max([3, 4, 5])
5
max(["one", "two", "three", "four", "five"])
'two'

What if I want to find the longest one?

"one" > "two"
False
max(["one", "two", "three", "four", "five"], key=len)
'three'
def mylen(word):
    print("mylen", word)
    return len(word)
max(["one", "two", "three", "four", "five"], key=mylen)
mylen one
mylen two
mylen three
mylen four
mylen five
'three'
"two" < "three"
False
# with key=len
len("two") < len("three")
True

Methods

Methods are special kind of functions that work on a value/object.

x = "Hello"
x.upper()
'HELLO'

upper is a method available on objects of type str.

type(x)
str
n = 1
n.upper() # doesn't work
AttributeError: 'int' object has no attribute 'upper'
"mathematics".count("mat")
2
"mathematics".replace("mat", "rat")
'ratheratics'

Spliting and joining strings

sentence = "Antyhing that can go wrong, will go wrong."
sentence.split()
['Antyhing', 'that', 'can', 'go', 'wrong,', 'will', 'go', 'wrong.']
len(sentence.split())
8
def wordcount(sentence):
    return len(sentence.split())
wordcount(sentence)
8
sentences = [
    "one two three",
    "one two three four",
    "one two three four five",
    "a b c d e f g"]    
max(sentences, key=wordcount)
'a b c d e f g'
sentence.split() # split on any white space
['Antyhing', 'that', 'can', 'go', 'wrong,', 'will', 'go', 'wrong.']
sentence.split(",") # split on the given delimiter
['Antyhing that can go wrong', ' will go wrong.']

Let’s see how to join the strings back.

"-".join(["a", "b", "c"])
'a-b-c'
":".join(["a", "b", "c"])
'a:b:c'
"".join(["a", "b", "c"])
'abc'
sep = "-x-"
sep.join(["a", "b", "c"])
'a-x-b-x-c'

Modules

import time
time.asctime()
'Mon Sep 25 05:25:51 2023'
time.asctime()
'Mon Sep 25 05:25:56 2023'
time 
<module 'time' (built-in)>
print(time)
<module 'time' (built-in)>
t = time
type(time)
module
t
<module 'time' (built-in)>
t.asctime()
'Mon Sep 25 05:26:43 2023'
!date
Mon Sep 25 05:27:12 AM UTC 2023

Let’s see how to implement it in Python.

%%file date.py
import time

print(time.asctime())
Writing date.py
!python date.py
Mon Sep 25 05:27:45 2023
!date
Mon Sep 25 05:27:48 AM UTC 2023

The os module

import os
os.listdir(".")
['index.qmd',
 'assignments.qmd',
 'assignment-01.qmd',
 '_quarto.yml',
 '_book',
 'course.qmd',
 'references.qmd',
 '.ipynb_checkpoints',
 'date.py',
 'args.py',
 'styles.css',
 'echo.py',
 'syllabus.qmd',
 'countdown.py',
 'session2.ipynb',
 'square.py',
 '.quarto',
 'lab.qmd',
 'script.js',
 'session1.ipynb.invalid',
 'schedule.qmd',
 'session1.ipynb',
 'hello.py',
 'live-notes.qmd',
 'schedule.ipynb',
 'references.bib']
len(os.listdir("."))
26
# os.path.getsize("session-02.ipynb")
os.path.getsize("session2.ipynb")
82059