0% found this document useful (0 votes)
44 views1,229 pages

Slides Combined

The document outlines the fundamentals of software development, focusing on problem-solving steps, data structures, and algorithms. It emphasizes the importance of programming languages, particularly Python, for building data structures and implementing algorithms. Key topics include representation of data types, writing programs, and understanding Python's syntax and built-in functions.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
44 views1,229 pages

Slides Combined

The document outlines the fundamentals of software development, focusing on problem-solving steps, data structures, and algorithms. It emphasizes the importance of programming languages, particularly Python, for building data structures and implementing algorithms. Key topics include representation of data types, writing programs, and understanding Python's syntax and built-in functions.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 1229

IT5001 Software Development

Fundamentals

1. Introduction

Rajendra Prasad Sirigina


August-2023

1
Software Development

Steps involved in problem-solving:

Abstraction/ Reasoning Solution


Problem Representation

Data Structures Algorithms

Programming languages provide tools to:


1. build data structures
2. do reasoning

2
Representation

• Numbers

• Strings

• Arrays

• Multi-dimensional Arrays

• Graphs and Trees

3
Algorithms

• Named for al-Khwārizmī (780-850)


 Persian mathematician

• Many ancient algorithms


 Multiplication: Rhind Papyrus
o Babylon and Egypt: ~1800BC
 Euclidean Algorithm: Elements
o Greece: ~300BC
 Sieve of Eratosthenes
o Greece: ~200BC
Algorithm
 An algorithm is a well-defined computational
procedure consisting of a set of instructions,
that takes some value or set of values as input,
and produces some value or set of values as
output.

Input Algorithm Output

‘Algorithm’ stems from ‘Algoritmi’, the Latin form of al-


Khwārizmī, a Persian mathematician, astronomer and geographer.
Source: http://en.wikipedia.org/wiki/Algorithm
Algorithm
 Ways of representing an algorithm:
Flowchart Pseudocode

get a number

read the number and store it in N

if N is less than zero


print negative number
else
print positive number
end If

https://en.wikipedia.org/wiki/Flowchart
Algorithm Vs Program

Algorithm Program
• Ideas • The final code on a
machine

get a number

read the number and store it in N

if N is less than zero


print positive number
else
print negative number
end If
Writing a Program

• Requires

 Understanding of language issues


o Syntax and Semantics

 Data Structures
o Representation of the problem

 Reasoning ability
o Algorithms

9
An overview of
Why are we learning Python?

• Clear and readable syntax


• Intuitive
• Natural expression
• Powerful
• Popular & Relevant

• Example: Paypal
 ASF XML Serialization
o C++
• 1580 lines
o Python
• 130 lines
Python Program without Learning

a = 1
b = 2
c = a + b
if c < 0:
print('Yes')
else:
print('No')

Intuitive!
Pseudo Code to Program

Algorithm Program

get a number

read the number and store it in N

if N is less than zero


print positive number
else
print negative number
end If
The Environment: IDLE
• IDLE as an IDE
 IDLE:
o Integrated development and learning environment

 IDE:
o Integrated development environment
• Edit, run and debug

• Other tools
 Jupyter notebook
 PyCharm
 Spyder
 Visual Studio Code, etc.
A Screenshot of IDLE

Console
Editor
- Input
and Your
- output
program

Let’s go for
some demo
You can

• Directly type into the console

• In which, we seldom do this


Or Run a file

Output of your
Representation
Integers, Floats, Boolean,
Numbers
etc.

Strings, Tuples

Sequences
Built-in Types*

Lists

Set Types Set

Mapping Types Dictionaries

Modules, Classes, Class


Others
Instances, Methods, etc.
20
*List is incomplete
Built-in Types

Type Description Immutable?


int Integer Yes Primitive types
float Floating-point number Yes
bool Boolean value Yes
string Character String Yes
list Sequence of objects No
tuple Sequence of objects Yes
set Unordered set of distinct objects No
dict Associative Mapping (dictionary) No

Immutable: Cannot modify


21
Numbers: Numeric Types
• Integers: int

• Floats: float
 Stores real numbers as binary fractions
 64-bit double precision*

• Self Exercise:
 Convert the decimal numbers 0.375 and 0.1 to binary. What do you learn from the
conversion?

https://en.wikipedia.org/wiki/Double-precision_floating-point_format
22
https://docs.python.org/3/tutorial/floatingpoint.html#tut-fp-issues
Boolean Type

• Following are evaluated to False


 False : Keyword
 None : Keyword
 0, 0.0, 0j : Value Zero (int, float, complex)
“ ” : Empty String
[] : Empty List
{} : Empty Dictionary
 range(0) : Iterator
 set() : Empty set
Will learn them in
subsequent weeks

• Rest are evaluated to True

23
Identifiers

• User-defined names for objects


 Can enhance readability

• Rules
 First character should be an alphabet or underscore ( _ )
 Other characters can be numbers and underscore
 Special characters not allowed
 Names are case sensitive assignment operation

24
Multiple Assignments
Python is Dynamically Typed

• No need to declare
object type

• Interpreter
automatically
recognizes the type

26
• Keywords cannot be used as identifiers

• Builtins can be used as variables


• but don’t do it

27
builtins

28
Keyword Types
Type Example
Value Keywords True, False, None
Operator Keywords and, or, not, in, is
Control Flow Keywords if, else, elif
Iteration Keywords for, while, break, continue, else
Structure Keywords def, class, with, as, pass, lambda
Returning Keywords return, yield
Import Keywords import, from, as
Exception-handling Keywords try, except, raise, finally, else, assert
Asynchronous Programming async, await
Keywords
Variable Handling Keywords del, global, nonlocal

29
Operators

• Arithmetic Operators

• Logical Operators

• Equality Operators

• Comparison Operators

30
Arithmetic Operators

31
Mixed mode arithmetic

• If operands are of different types?

• Narrower (less general) and Wider (more


general) Types
 Float is wider (more general) than integer
o All integers are floats but not vice-versa

• Narrower type is promoted to wider type


 Integer is promoted to float

32
Comparison Operators

What is the difference between == and is?

33
is operator

34
is operator

• Binary operator
 Returns true if identity of both operands is same

• What is identity?

Namespace objects

500
x

500
y

35
Keyword is

• Binary operator
 Returns true if identity of both operands is same

• What is identity?

Namespace

500
x

36
Logical/Boolean Operators

Operator Operation Result Remark


and x and y If x is false, then x, else y • Short-circuit operator
(conditional and) • Only evaluates the second
argument if the first one is
true
or x or y If x is false, then y, else x • Short-circuit operator
(conditional or) • Only evaluates the second
argument if the first one is
false

not not x If x is false, then True, • Low priority than non-


(unary negation) else False Boolean operators
• Ex: not a == b means not
(a==b)

https://en.wikipedia.org/wiki/Short-circuit_evaluation
Demo in IDLE 37
and Operator

x and y: if x is false, then x, else y

38
or Operator

x or y: if x is false, then y, else x

39
not Operator

not x: If x is false, then True, else False

40
Augmented Assignment Operators

Operation Description
x += y x=x+y
x *= y x=x*y
x /= y x=x/y
x // = y x = x //y
x ** = y x = x**y

41
Expressions

• Expressions
 A piece of syntax evaluated to some value
 Combination of operators and operands
o Value is an expression
o Variable is an expression
o Combination of values, variables and operators is also an expression

42
Standard IO: Input

• Input

• Type Casting
 Conversion of one type to other
 Example:

43
Standard IO: Output

44
Precedence

Operator Description

() Parenthesis

** Exponentiation

+x, -x x unchanged, x negated

*, /, //, % Multiplication, division, floor division,


remainder
+, - Addition, Subtraction

in, not, <, <=, >, >=, ==, != Membership, comparison and identity tests

not x Boolean NOT

and Boolean AND

or Boolean OR

45
Precedence

(4-5) * 3 – 7 % 4 ** 2 / 3 Operator

()
-1 * 3 - 7 % 4 ** 2 / 3 **

+x, -x
-1 * 3 - 7 % 16 / 3 *, /, //, %

+, -
-3 - 7 % 16 / 3 in, not, <, <=, >, >=, ==, !=

not x
-3 - 7 / 3 and

or
-3 - 2.333334

-5.2333334 Equal precedence:


Association is from left to right

46
Strings

• Strings are indexed sequence of characters

• Example Strings

 It is IT5001

 It’s IT5001

 “It is IT5001,” said Alice

 C:\new\IT5001

47
Strings

• Single quotes:
 Example
o It is IT5001
o “It is IT5001,” said Alice
o It’s IT5001

escape character

48
Strings

• Double quotes
 Example:
o It is IT5001
o It’s IT5001
o “It’s IT5001,” said Alice.

escape character

49
Strings

• Triple Quotes and Triple Double Quotes

 Doesn’t require escape character for single quote and double quotes within
strings

 Support multiline strings

50
String Manipulations

• String Operators

• Built-in String Functions

• String Indexing and Slicing

• Built-in String Methods

• String Formatting

51
String Operators

Operator Operation Result Example

+ x+y Concatenates strings x and y ‘This is ’ + ‘IT5001’ = ‘This is IT5001’

* x*c A new string with ‘c’ copies of string x, ‘Hi’*2 = ‘HiHi’


where c is integer
in x in y Returns True if string x is in string y ‘Hi’ in ‘Hi IT5001’  True

not in x not in y Returns True if string x is not in string y ‘Hi’ not in ‘Hi IT5001’  False

52
String Operators

53
Built-in String Functions

Function Return Value Example


len() Length of the string len(‘Hi’) = 2
chr(i) A string representing a character whose Unicode chr(123) = ‘{’
point is the integer 𝑖𝑖, 0 < 𝑖𝑖 < 1114111
- Returns a single character string for an input
integer
ord() ASCII value of character (string with ) ord(‘{’) = 123
- Returns integer value for an input single
character string
str() Returns string representation of an object str(2.5) = ‘2.5’

https://docs.python.org/3/library/functions.html
54
Lexicographical Ordering
Unicode of Characters

lexicographical ordering: first the first two letters are compared, and if they
differ this determines the outcome of the comparison; if they are equal, the next
two letters are compared, and so on, until either sequence is exhausted. 55
String Indexing and Slicing

• Strings are represented as compact arrays

string_example = ‘This is IT5001’

Indexing:

0 1 2 3 4 5 6 7 8 9 10 11 12 13

index T h i s i s I T 5 0 0 1

-14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1

Slicing:

string_example[start : end : stride]

56
String Indexing and Slicing

string_example = ‘This is IT5001’

Indexing:

0 1 2 3 4 5 6 7 8 9 10 11 12 13

index T h i s i s I T 5 0 0 1

-14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1

57
String Indexing and Slicing

string_example = ‘This is IT5001’

Indexing:

0 1 2 3 4 5 6 7 8 9 10 11 12 13

index T h i s i s I T 5 0 0 1

-14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1

58
Immutability of Strings

59
String Methods

• Case Conversion
 upper, lower, title, etc.

60
f-strings

• f-strings
 Strings prefixed with ‘f’
 ‘f’ stands for formatted strings
 Expressions can be embedded in strings
o Expressions evaluated at run time.
 Contains replacement fields, delimited by curly braces

61
Raw Strings

• Raw Strings

 Strings prefixed with literal ‘r’

62
Conclusion

• Numeric and Boolean Types

• Operators and Precedence

• Expressions and Statements

• Strings, String Operators, String Functions, and String Methods

• Immutability

• Next Class: Libraries and User-defined Functions

63
Miscellaneous
Namespaces

64
Namespaces

Builtin Contains builtin names


Namespace

Global Contains user-defined variable names

Enclosed
will be discussed in
subsequent lectures
Local

65
Builtin Namespace

• Contains names of __builtin__ module:


 Datatypes
o Int, float, etc.
 Functions
o print, input, etc.
 Exceptions
o NameError, SyntaxError, etc.

• Check dir(__builtins__)

• Will be created (destroyed) when Python interpreter starts (closes)

• What if you want to use a name in builtins?

66
Global Namespace

67
How are objects stored?
Heap Memory

Id (Address) Objects
0x1 2
0x2 2.0
my_int= 0x1

my_float = 0x2

Global Namespace

dir

print
Builtin Namespace

Interpreter first searches names in Global Namespace


If name is not there in global namespace, searches in builtin namespace
If name is not in builtin namespace, throws ‘NameError’
68
How are objects stored?

• x=2 x 2
• y=2
• y=3 3
y
• y = 4.0

4.0

69
How are objects stored?

Demo: pythontutor.com

70
Memory Management

• Python does memory management automatically

• Private heap to store objects

• Memory management depends on object type

71
Data Model: Objects, Values, and Types

• Objects are Python’s abstraction for data


• Data in program is represented by objects and relation between objects

Object Object’s address in memory


Identity Can be obtained using id()
Specifies the types of object
Type Can be obtained using type()

Value Immutable: numbers, strings, tuples, etc.


Mutable: lists, dictionaries
Reference Count Why is this behaviour?

72
IT5001 Software Development
Fundamentals

2. Functions (Callable Units)

Rajendra Prasad Sirigina


August-2023

1
Agenda: Functions

• Python Modules and Packages


 Namespaces
 Scope
• User-defined functions
 Arguments
o Positional
o Keyword
o Default
 Return Statement
o print vs return
 Function Tracing
o Namespaces
o Local namespace
• Pure Functions

2
Why Functions?

3
Example: Drawing a square

What if we need to draw another square at a different location?


4
Drawing another square

5
What if you want more squares?

• Involves a lot of repetitions

• Instead write code to draw a square and reuse it

• How to do it?
 Use functions

• Functions allows reusability


 No need to rewrite the code for same functionality

6
Abstraction

Input Output

• Usability
 User only needs to know input arguments and output data types

• Declarative style of programming


 Tell the system what you want

7
Modularity

A Giant Module
(A program that do many things)

Vs

Modular Architecture

Module 1 Module 2 Module n

programs that only do one thing 8


Functions: Mathematics

• A mapping from input to output

𝑥 𝑦
name of the function 𝑓
one-to-one

𝑦 𝑓 𝑥 many-to-one

output argument many-to-one

Domain Range

9
Functions in Programming

• A self-contained block of code

• Known as subroutines, methods, procedures, etc.

10
Types of Functions
Domain Range
• Pure functions 𝑓
 Functions without side-effects
 Only mapping
 Outputs depend only on inputs

side-effect I/O etc.

• Functions with side-effects


 Side-effects: I/O tasks
o Taking inputs from keyboard, reading data from a file, etc.
o Printing output to screen, writing data to a file, etc.

• Higher-order Functions (in Week 4)


 Functions that accept functions as inputs and/or return functions as outputs
ℎ 𝑥 𝑓 𝑔 𝑥

11
Functions in Python

• Built-in Functions
 Builtin module is loaded automatically
o No need to import
 Examples: print(), input(), id(), etc.

• Functions from Python modules and packages


 Not loaded automatically
 Need to import them when needed
 Example: function in modules like math, statistics.

• User-defined Functions

• Special function
 main()

12
Built-In Functions

13
https://docs.python.org/3/library/functions.html
Functions from Python Modules and Packages

• Import packages
 Example:
o math package

• We can import modules


 Syntax
o import <module_name>
o from <module_name> import <name(s)>

 Examples
o import math
o from math import cos, sin
o from math import *

14
Namespaces: Importing Modules

Syntax:

import <module_name>
<module_name>.<object_name>
sin, pi, etc.

Example: dedicated
math
namespace
import math namespace
for each
math.pi imported
math.sin(math.pi/2) module within
global Global
namespace Namespace

dir
print

Builtin Namespace

15
Importing Modules

16
Namespaces: Importing Multiple Modules

Syntax:

import <module_1>, <module_2> math


namespace
<module_1>.<object_name>
<module_2>.<object_name> sin, pi, etc.

statistics
namespace
Example: mean,
variance, etc.

Global
Namespace

dir
print

Builtin Namespace

17
Namespaces: Importing Objects from Modules

Syntax:

from <module_name> import <object_name>


<module_name>.<object_name>
sin, pi, x

Example: Global
Names from Namespace
math module
are imported
into global
namespace
dir
print

Builtin Namespace

18
You don’t want to be like this in real life

Try NOT to import


too many packages
User-defined Functions

• Simple functions
• Doc strings
• Arguments (Parameters)
 Positional
 Keyword
 Default
• Parameter Passing
 Pass-by Value
 Pass-by Reference
 Pass-by Assignment

20
User-Defined Functions
function name

keyword

<statement>
<statement>
def function_name (argument(s)): y = function_name(argument)
<statement>
<statement>
.
<statement>: Statement that is part
. of the function scope
. <statement>: Statement that is out of
<statement> function scope
<statement>
<statement>

white space
(indicates the scope of the function)
21
User-Defined Functions

22
Return Statement

• It does two things


 Terminates the function
 Return statement pass the output of function to the calling function

def function_name (arg_1, arg_2,…, arg_n):


<statement>
<statement>
.
.
.
return <statement>

23
Example

𝑥 𝑥
𝑦 𝑓 𝑥 ,𝑥
2

name of function arguments

Block of Code

keywords white space Value returned by the function

24
Arguments

• Provide input to functions

def function_name (arg_1, arg_2,…,arg_n): name of the function


<statement>
<statement> 𝑦 𝑓 𝑥1, 𝑥 2, . . , 𝑥 𝑛
.
. output
. arguments
<statement>

25
Doc String

• Contains information about function


 Describes how to use the function
 Can access it using help/doc methods

26
Types of Arguments

• Positional arguments

• Keyword arguments

• Default/optional arguments

27
Positional Arguments

28
Positional Arguments

• Number of arguments are important

• Should take care of order of arguments

29
Keyword Arguments

• Order is not important

• Names of the arguments should be the same as in function definition

30
Default/optional arguments

• Assign default values in function definition


default argument should always be at the end

• Default arguments can be omitted while calling a function

• Default argument can be assigned a different value

31
Return vs Print

Vs Returns None

32
Revisit Drawing Squares

• How to generalize the code?

• Retain similarities
• Parametrize differences

33
Drawing Squares using Functions

34
Namespaces

Builtin

Namespace Global

Enclosed

Local

35
Namespaces: User-defined functions

Local namespace
is created when
the user-defined Local Namespace
function is called

Global Namespace

Builtin Namespace

36
Namespaces: Imported Modules and User-defined
functions

Local namespace
is created with in
global namespace
when the user-
Local Namespace
defined function is
called

imported_module_1
Dedicated Namespace
namespace for
each imported
module imported_module_2
Namespace

Global Namespace

Builtin Namespace

37
Functions: Tracing 1

38
Functions: Tracing 1
0x1 2
0x2 4

Memory

x = 0x1
y = 0x2

Global namespace

Builtin namespace
39
Functions: Tracing 1
0x1 2
0x2 4

Memory

x = 0x1
y = 0x2

Global namespace

Builtin namespace
40
Functions: Tracing 1
0x1 2
0x2 4

Memory

x = 0x1
y = 0x2

Global namespace

Builtin namespace
41
Functions: Tracing 1
0x1 2
0x2 4
0x3 3
0x4 6

x = 0x3
y = 0x4

sum_two_numbers
Memory

x = 0x1
y = 0x2

Global namespace

Builtin namespace
42
Functions: Tracing 1
0x1 2
0x2 4
0x3 3
0x4 6

x = 0x3
y = 0x4

sum_two_numbers
Memory

x = 0x1
y = 0x2

Global namespace

Builtin namespace
43
Functions: Tracing 1
0x1 2
0x2 4
0x3 9

Memory
x = 0x1
y = 0x2
z = 0x3

Global namespace

Builtin namespace
44
Functions: Tracing 2

45
Functions: Tracing 2
0x1 2
0x2 4

Heap Memory

x = 0x1
y = 0x2

Global namespace

Builtin namespace
46
Functions: Tracing 2
0x1 2
0x2 4

Heap Memory

x = 0x1
y = 0x2

Global namespace

Builtin namespace
47
Functions: Tracing 2
0x1 2
0x2 4

Heap Memory

x = 0x1
y = 0x2

Global namespace

Builtin namespace
48
Functions: Tracing 2
0x1 2
0x2 4
0x3 3

x = 0x3

sum_two_numbers
Heap Memory

x = 0x1
y = 0x2

Global namespace

Builtin namespace
49
Functions: Tracing 2
0x1 2
0x2 4
0x3 3

x = 0x3

sum_two_numbers
Heap Memory

x = 0x1
y = 0x2

Global namespace

Builtin namespace
50
Functions: Tracing 2
0x1 2
0x2 4
0x3 3
0x4 7

Heap Memory

x = 0x1
y = 0x2
z = 0x4
Global namespace

Builtin namespace
51
Side-effects

• Functions with side-effects Domain Range


𝑓
 Side-effects: I/O tasks
o Taking inputs from keyboard,
reading data from a file, etc.
o Printing output to screen, writing
data to a file, etc.
side-effect I/O etc.

• Pure functions
 Functions without side-effects
 Only mapping
 Outputs depend only on inputs

52
Pure Function

Pure function: Yes/No? Pure function: Yes/No?

53
Summary

• Modules and Packages

• User-defined functions

• Argument Types

• Print vs Return

• Pure Function

54
IT5001 Software Development
Fundamentals

3. Control Structures
Sirigina Rajendra Prasad

(Slide Credit: Prof. Alan, SoC, NUS)


1
Example: Solving a Quadratic Equation
Example: Solving a Quadratic Equation
Example: Solving a Quadratic Equation

• Remember what we learned in high school…

• Let’s try to implement it in Python


However…

• Why?
delta = 25-24 = 1 > 0

delta = 1 – 32 = -31 < 0


Example: Solving a Quadratic Equation

• Remember what we learned in high school…

• If delta < 0
 The equation has no real solution

• So we cannot call sqrt() if delta is negative


Control Structures
The basic building blocks of programming
Control Structures

Sequence • Default

True False
• Also called ?
Selection branching

• Also called
Repetition
False ?
loop
True
Making Choices
Control Structure: Selection True
?
False

If (a condition is true)
Do A
Else
Do B
Can be MORE THAN one single
instruction
• For example:
If (I have $1000000000000000)
Buy a car
Eat a lot of buffets
Go travel
Quit NUS!
Else
Be good and study
Control Structure: Selection True
?
False

If (a condition is true)
Do A
Else
Do B
Can be MORE THAN one single
• For example: instruction
If (I have $1000000000000000)
If (I am heartless)
Buy a car
Eat a lot of buffets
Go travel
Quit NUS!
Else
donate all the money to charity Nested “if”
Else
Be good and study
Control Structure: Selection True
?
False

If (a condition is true)
Do A
Else
Do B
Can be WITHOUT “else”
• For example:
If (I have $1000000000000000)
Buy a car
Eat a lot of buffets
Go travel
Quit NUS!
Else
Be good and study
Control Structure: Selection True
?
False

If (a condition is true)
Do A
Else
Do B
Can be MORE THAN one single
instruction
• For example:
If (I have $1000000000000000)
Buy a car
Eat a lot of buffets
Go travel
Quit NUS!
Else
Be good and study
Condition

condition
If the condition is True
If the condition is False
Conditional

Syntax Example
if <expr>: >>> my_money = 1000
statement(s) >>> if my_money > 0:
print('Good')
'Good'

indentation
Conditional

Syntax Example
if <expr>: >>> my_money = 1000
statement(s) >>> if my_money > 0:
print('Good')
print('Good')
print('Good')
indentation
'Good'
'Good'
'Good'
Conditional

Syntax Example
if <expr>: >>> my_account = 1000
statement(s) >>> if my_account > 0:
else: print('rich')
statement(s) else:
print('broke')
‘rich'
Conditional (Nested)

Syntax Example
if <expr>: a = 4
if <expr>: if a < 10:
statement(s) if a < 1:
print('Here')

Print nothing
Conditional

Syntax Example
if <expr>: >>> my_account = 1000
statement(s) >>> if my_account < 0:
else: print('poor')
statement(s) else:
if my_account > 1:
Clumsy print(‘v rich')

v rich
Conditional

Syntax Example
if <expr>: >>> a = -3
statement(s) >>> if a > 0:
elif <expr>: print('yes')
statements(s) elif a == 0:
else: print('no')
statement(s) else:
print('huh')
'huh'
Conditional

Syntax Example
if <expr>: >>> a = 4
statement(s) >>> if a > 0:
elif <expr>: print('yes')
statements(s) elif a == 0:
elif <expr>: print('no')
statements(s) elif a == 4:
else: print('ahh')
statement(s) else:
print('huh')
'yes'

Can be many
T F
a < 0

e.g. T F
print(‘yes’) a==0
>>> a = 4
>>> if a < 0:
print('yes')
print(‘no’)
elif a == 0: T F
a==4
print('no')
elif a == 4:
print('ahh')
print(‘ahh’) print(‘huh’)
else:
print('huh')
'ahh'
Homework: Figure out ALL conditions

condition
Repetition
Control Structure: Repetition False ?

• While (a condition) True


 Do something

• For example
While (I am hungry)
Eat a bun

• Again, can be more than one single instruction


While(I have money in bank)
Take money out from bank
Eat an expensive meal
While(I have money in my wallet)
Go Shopping
Iteration
the act of repeating a process with
the aim of approaching a desired
goal, target or result.
- Wikipedia
Three Types of Loops

• Must run exactly N times


• Run any number of times
• Run at most N times
 Check all True (or check all False)
 Find any True (or False)
Three Types of Loops

• Must run exactly N times


• Run any number of times
• Run at most N times
 Check all True (or check all False)
 Find any True (or False)
For loop

• Uses iterable objects to repeatedly execute a series of tasks

• Number of repetitions are equal to number of items provided by iterable


object

• Let us first look at iterable objects

34
Iterable and Iterators

Iterable iter( ) Iterator next( )


object object

 Can be looped over  Repeated calls of next() method return next item
 Any object with __iter__ method is iterable from iterator object
 Builtin Iterables:  If no further items in iterator, next( ) method
 range, strings, lists, tuples raises StopIteration exception
 User-defined iterable objects
 Generator functions

35
Iterables

• This week:
 range() - builtin iterable

• Subsequently
 strings
 user-defined iterators
 lists/tuples/dictionary

36
Builtin Iterable: range()

• range(start, stop, step)


 Generate sequence of numbers from start (inclusive) to stop (exclusive),
incremented by step

 start and step are optional arguments


o Default Values:
• start = 0
• step = 1

37
Repetition Flow Control: “For”

Syntax Example
for i in range(n,m): for i in range(0,5):
statement(s) print(i)

0
1
2
3 Exclusive
4
Repetition Flow Control: “For”

Example Interpreted as
for i in range(0,5): i=0
print(i) print(i)
i=1
0 print(i)
1 i=2
2 print(i)
3 i=3
4 print(i)
i=4
print(i)
Iterative Factorial

Idea
• Start with 1, multiply by 2, multiply by 3, … , multiply by n.
• 𝑛𝑛! = 1 × 2 × 3 ⋯ × 𝑛𝑛

Product Counter
120
24
1
6
2 × 3
5
4
1
2
Iterative Factorial

• 𝑛𝑛! = 1 × 2 × 3 ⋯ × 𝑛𝑛
• Computationally
• Starting:
• product = 1
• counter = 1
• Iterative (repeating) step:
• product  product × counter
• counter  counter + 1
• End:
• product contains the result
Computing Factorial

• 𝑛𝑛! = 1 × 2 × 3 ⋯ × 𝑛𝑛
• Factorial rule:
• product  product × counter
• counter  counter + 1 product counter
non-inclusive.
def factorial(n): Up to n. 1 2
product = 1 1x2 = 2 3
for counter in range(2, n+1): 1x2x3=6 4
product = product * counter
1x2x3x4=24 5
return product
120 6
720 7
factorial(6)
for loop

• for <var> in <sequence>:


• <body>

• sequence
 a sequence of values
• var
 variable that take each value in the sequence
• body
 statement(s) that will be evaluated for each value in the sequence
range function

• range([start,] stop[, step])

• creates a sequence of integers


May omit
 from start (inclusive) to stop (non-inclusive)
 incremented by step
Examples

for i in range(10):
print(i)

for i in range(3, 10):


print(i)

for i in range(3, 10, 4):


print(i)
Example
Flipping coins
Flipping a coin

• A coin is “fair” if the probably of getting a head is equal to a tail


 P(head) == P(tail) == 0.5

• How to test a coin is fair?

• Flip 1000 times!


Write a Pseudo Code for the Experiment

• I will flip a coin 1000 times and FOR EACH FLIP


 I will record how many times I had flipped
 If it is a head, I will record the number of heads
What you
repeat for
EACH time
Flipping Coins

Randomly
generate
either 0 or 1
while loop

• while <expression>:
• <body>

• expression
 Predicate (condition) to stay within the loop
• body
 Statement(s) that will be evaluated if predicate is True
Repetition (Infinite)

while True: a = 0
print(‘Ah...’) while a > 0:
a = a + 1
print(a)
Repetition
indentation

Syntax Example
while <expr>: >>> a = 0
statement(s) >>> while a < 5:
a = a + 1
print(a)
1
2
3
4
5
Another Iterative process

def factorial(n): product counter


product, counter = 1, 1
1 1
while counter <= n:
1 2
product = (product *
2 3
counter)
6 4
counter = counter + 1
24 5
return product
120 6
720 7
factorial(6)
counter > n (7 > 6)
return product (720)
while (not edge in front): while (not edge currently):
run() run()
Another Iterative process

def factorial(n): product counter


product, counter = 1, 1
1 1
while counter <= n:
1 2
product = (product *
2 3
counter)
6 4
counter = counter + 1
24 5
return product
120 6
720 7
factorial(6)
counter > n (7 > 6)
“<=“ or “<“ ? return product (720)
Randomly
generate
either 0 or 1
Repetition (nested)
indentation

Syntax Example
while <expr>: def nestedWhile():
i = 0
while <expr>: while i < 5:
i += 1
statement(s) j = 0
while j < 3:
j += 1
print ('#' * j)
Repetition, a Very Common
Pattern
9 out of 10 times you will
do For loop
>>> a = 0 for i in range(0,N):
>>> while a < N: do something
a = a + 1
do something
Three Types of Loops

• Must run exactly N times


• Run any number of times
• Run at most N times
 Check all True (or check all False)
 Find any True (or False)
Sum Some Numbers
Sum Some Numbers

• You do not know how many numbers will the user enter
Why do we need to repeat these?
Loop Terminating Condition

• Must run exactly N times


• Run any number of times
• Run at most N times
 Check all True (or check all False)
 Find any True (or False)

• If we do not know how many times do we need, when do we know we


finish looping?
Loop Terminating Condition

• When will the loop terminate?

• When
 num == ‘bye’? Or
 num!= ‘bye’ ?
Loop Terminating Condition

• When will the loop terminate?

• The loop body will keep repeating if the condition is true


• The you break the loop if the condition is not true anymore
Three Types of Loops

• Must run exactly N times


• Run any number of times
• Run at most N times
 Check all True (or check all False)
 Find any True (or False)
Check if a String is all Alphabets

• Given a string, example, ‘abc123’


• Check if all the characters are alphabets
 Return True or False

• In real life, how do you check?

• For example, if you are the teacher with a lot of test scripts, how do you
check if “all are marked”?
Goal: All are Alphabet

• I just need one of the answers:


 Yes: if all are alphabet
 No: if there exists one not alphabet
• Combining
 You check the character one-by-one
 If the current one is alphabet, do nothing, check the next
o Else return “No”!
 Until finishing all character all checked, return “Yes”

Which line you


repeat a lot of
times?
Goal: All are Alphabet

• I just need one of the answers:


 Yes: if all are alphabet
 No: if there exists one not alphabet
• Combining
 You check the character one-by-one
o If the current one is alphabet, do nothing, check the next
• Else return “No”!
 Until finishing all character all checked, return “Yes”

In Python, you
indent the
statements
needed to be
loop
Goal: All are Alphabets

• Combining
 You check the character one-by-one
o If the current one is NOT alphabet, return “No”!
 Until finishing all character all checked, return “Yes”
Goal: All are Alphabets

• Combining
 You check the character one-by-one
o If the current one is NOT alphabet, return “No”!
 Until finishing all character all checked, return “Yes”
Goal: All are Alphabets

• Combining
 You check the character one-by-one
o If the current one is NOT alphabet, return “No”!
 Until finishing all character all checked, return “Yes”
Goal: All are Alphabets

• Combining
 You check the character one-by-one
o If the current one is NOT alphabet, return “No”!
 Until finishing all character all checked, return “Yes”
How many times?

• How many times we reach this line if len(string) = N?


 You check the character one-by-one
o If the current one is NOT alphabet, return “No”!
 Until finishing all character all checked, return “Yes”

• Worst case: N times


• But maybe less than N
Provided that we have a function

• To check if a character is an alphabet


Three Types of Loops

• Must run exactly N times


• Run any number of times
• Run at most N times
 Check all True (or check all False)
 Find any True (or False)

• Check all True similar to check all False


 E.g. check if all characters are NOT alphabet?
Three Types of Loops

• Must run exactly N times


• Run any number of times
• Run at most N times
 Check all True (or check all False)
 Find any True (or False)

• Check any True?


 Return the reverse of “check all False”
“For” vs “While”

• When to use “for” and when to use “while”?


• “For”
 You know how many times before hand
 Namely, anything in the body of the loop will NOT change the number of times
you repeat the loop
 E.g. printing out all the data in a spreadsheet
• “While”
 You may not know how many times you need to repeat
 The number of times is depended on the “condition”, in which, may change
unpredictably inside the loop
 E.g. while the player haven’t guess the right answer, keep guessing
Lastly: break & continue

for j in range(10): 0
print(j) 1
Break out
if j == 3: 2
of loop
break Jump 3
print("done") done

for j in range(10): 1 Continue with


Jump 3 next value
if j % 2 == 0:
continue 5
print(j) 7
print("done") 9
done
Let’s play a game
>>> guessANum()
I have a number in mind between 0 and 99
Guess a number: 50
Too big
Guess a number: 25
Too big
Guess a number: 12
Too big
Guess a number: 6
Too small
Guess a number: 9
Too big
Guess a number: 7
Bingo!!!
>>>
guessANum.py
import random

def guessANum():
secret = random.randint(0,99) # 0 <= secret <= 99
guess = -1
print('I have a number in mind between 0 and 99')
while guess != secret:
guess = int(input('Guess a number: '))
if guess == secret:
print('Bingo!!! You got it! ')
Repeat
until the
elif guess < secret:
print('Your number is too small')
else: condition
print('Your number is too big') is False

guessANum()
guessANum.py
import random

def guessANum():
secret = random.randint(0,99) # 0 <= secret <= 99
guess = -1
print('I have a number in mind between 0 and 99')
while guess != secret:
guess = int(input('Guess a number: '))
if guess == secret:
print('Bingo!!! The answer is ' + str(secret)))
elif guess < secret:
print('Your number is too small')
else: Repeat
print('Your number is too big') until the
condition
is False
guessANum()
How to write a love letter in Python

def show_my_love():
everything = True
you = everything
my_mind = you
while(my_mind == True):
print('I love you')
How to write a love letter in Python

def show_my_love():
everything = True #Everything I say is true
you = everything #You are everything to me
my_mind = you #All my mind is filled with you

# No 'if' in my love because it's unconditioal

while(my_mind == True): # My love is eternal


print('I love you')

# And there is no 'return' in my love


# because I do not expect any
Tips

• A “while” or “if” block starts with a colon “:”


• Remember
 When there is a colon, there are indentations
 When there are indentations, before these there is a colon

• The inclusive/exclusive range is a pain


IT5001 Software Development
Fundamentals
4. Functions, Scope, and Recursion
Sirigina Rajendra Prasad

1
Scope

2
Global vs Local Variables

• A variable which is defined in the main body of a file is called a global


variable. It will be visible throughout the file, and also inside any file
which imports that file. EXCEPT…
• A variable which is defined inside a function is local to that function. It is
accessible from the point at which it is defined until the end of the
function, and exists for as long as the function is executing.
• The parameter names in the function definition behave like local variables,
but they contain the values that we pass into the function when we call it.

Local namespace

x=0
Global namespace
Builtin namespace
Example

access global variable y

sum_two_numbers

x
y

Global namespace

Builtin namespace
4
Global Variable

x = 0 Refers to • This code will print


0
0
def foo_printx():
print(x)

foo_printx()
print(x) foo_printx

x=0
Global namespace
Builtin namespace
Global vs Local Variables

x = 0 • This code will print


999
0
def foo_printx():
x = 999
• The first ‘999’ makes
print(x) sense
• But why the second
foo_printx() one is ‘0’?
print(x)
Because, a new ‘x’
is born here!
Global vs Local Variables
A Global ‘x’

x = 0 • This code will print


999
0
def foo_printx(): Scope of the local ‘x’

x = 999
print(x)
Scope of the global ‘x’

foo_printx()
print(x)
A local ‘x’ that is created within the function
foo_printx() and will ‘die’ after the function
exits
Global vs Local Variables

x = 0

def foo_printx():
x = 999
x = 999
print(x) foo_printx

x=0
foo_printx() Global namespace
Builtin namespace
print(x)

8
Crossing Boundary

• What if we really want x = 0


to modify a global
variable from inside a
function? def foo_printx():
• Use the “global” global x
keyword x = 999
• (No local variable x is print(x)
created)
foo_printx()
Output:
print(x) 999
999
Crossing Boundary

x = 0

def foo_printx():
global x foo_printx

x = 999 x=0
print(x) Global namespace
Builtin namespace

foo_printx() Output:
print(x) 999
999
How about… this?

• Local or global?
x = 0
• Error!
• Because the line
def foo_printx(): “x=999” creates a local
print(x) version of ‘x’
x = 999 • Then the first print(x)
print(x) will reference a local x
that is not assigned
with a value
foo_printx() • The line that causes an
error
Parameters are LOCAL variables

Scope of x in
p1

Scope of x in
p2

Does not refer to

Scope of x in
p3
Practices (Convention)

• Global variables are VERY bad, especially if modification is allowed


• 99% of time, global variables are used as CONSTANTS
 Variables that every function could access
 But not expected to be modified

Convention:
Usually in all CAPs
Generator Functions

14
Generator Functions

def function(arg_1, arg_2,…, arg_n): def generator_function(arg_1, arg_2,…, arg_n):


<statement> <statement>
<statement> <statement>
. .
. .
. .
return <statement> yield <statement>

only difference

15
Return vs Yield

• With return • With yield statement:


statement: • State of the function
• State is not retained is retained between
after the function the calls
returns the value • Can have many yield
statements in
sequence

16
What is the state of a function?

• Namespace and the objects that are referred by names

0x1 2
0x2 4
x
y

Local namespace

Global namespace
Builtin namespace Heap Memory
17
Generator Functions: Examples

18
Generator Functions: Examples

19
Calling Other
Functions
Compare:
def hypotenuse(a, b):
return sqrt(sum_of_squares(a, b))

def sum_of_squares(x, y):


return square(x) + square(y)

def square(x): ?
return x * x a

Versus: b
def hypotenuse(a, b):
return sqrt((a*a) + (b*b))
The Call Stack
Michael Caine Just Ended An Eight Year Long Debate Over The Ending Of "Inceptio
Stack

• First in last out order


First in Last Out
The Stack (or the Call Stack)
The Stack (or the Call Stack)

>>> p1(3)
Entering function p1
Entering function p2
Entering function p3
Line before return in p3
Line before return in p2
Line before return in p1
9

FILO!
Going in
Exiting a
function
Namespaces: Calling Other Functions

Global Namespace

Builtin Namespace

29
Namespaces: Calling Other Functions

x =3

Namespace of p1( )

Global Namespace

Builtin Namespace

30
Namespaces: Calling Other Functions

x =3

Namespace of p1( )

x =3

Namespace of p2( )

Global Namespace

Builtin Namespace

31
Namespaces: Calling Other Functions

x =3

Namespace of p1( )

x =3

Namespace of p2( )

x =3

Namespace of p3( )

Global Namespace

Builtin Namespace

32
Namespaces: Calling Other Functions

x =3

Namespace of p1( )

x =3

Namespace of p2( )

x=3
output = 9

Namespace of p3( )

Global Namespace

Builtin Namespace

33
Namespaces: Calling Other Functions

x =3

Namespace of p1( )

x=3
output = 9

Namespace of p2( )

Global Namespace

Builtin Namespace

34
Namespaces: Calling Other Functions

x=3
output = 9
Namespace of p1( )

Global Namespace

Builtin Namespace

35
Namespaces: Calling Other Functions

Global Namespace

Builtin Namespace

36
p3()
p2()
p1()
Recursion

38
Recursion
A Central Idea of CS

Some examples of recursion (inside and outside CS):

Garfield dreaming
recursively.

Sierpinksi triangle

Droste effect
Recursive tree
Mandelbrot Fractal Endless Zoom
Recursion

• A function that calls itself


• And extremely powerful technique
• Solve a big problem by solving a smaller
version of itself
 Mini-me
Recursive Functions

• Function calls itself Base Case

Calling itself
(smaller problem)

42
Recursive Functions return 4*6 = 24

factorial(4)) return 3*2 = 6

factorial(3))

return 2*1 = 2

factorial(2))
return 1

factorial(1))

Base Case

43
Namespaces: Recursive Function

n=4
Namespace of factorial(4)

Global Namespace

Builtin Namespace

44
Namespaces: Recursive Function

n=4
Namespace of factorial(4)

n=3
Namespace of factorial(3)

Global Namespace

Builtin Namespace

45
Namespaces: Recursive Function

n=4
Namespace of factorial(4)

n=3
Namespace of factorial(3)

n=2
Namespace of factorial(2)

Global Namespace

Builtin Namespace

46
Namespaces: Recursive Function

n=4
Namespace of factorial(4)

n=3
Namespace of factorial(3)

n=2
Namespace of factorial(2)

n=1
Namespace of factorial(1)

Global Namespace

Builtin Namespace

47
Namespaces: Recursive Function

n=4
Namespace of factorial(4)

n=3
Namespace of factorial(3)

n=2
Namespace of factorial(2)

n=1 return value is 1

Namespace of factorial(1)

Global Namespace

Builtin Namespace

48
Namespaces: Recursive Function

n=4
Namespace of factorial(4)

n=3
Namespace of factorial(3)

n=2 return value is 2


Namespace of factorial(2)

Global Namespace

Builtin Namespace

49
Namespaces: Recursive Function

n=4
Namespace of factorial(4)

n=3 return value is 6


Namespace of factorial(3)

Global Namespace

Builtin Namespace

50
Namespaces: Recursive Function

return value is 24
n=4
Namespace of factorial(4)

Global Namespace

Builtin Namespace

51
Namespaces: Recursive Function

return value is 24

Global Namespace

Builtin Namespace

52
Recursive Vs Iteration

53
Fibonacci Number
(Recursion)
Starting from 2 Rabbits
How many ways to arrange cars?

• Let’s say we have two types of vehicles, cars and buses

• And each car can park into one parking space, but a bus needs
two consecutive ones
• If we have 1 parking space, I can only park a car
1 way

• But if there are 2 parking spaces, we can either park a bus or two
cars

2 ways

How many ways to arrange cars?

• So if we have 3 parking spaces, how many different ways can we park cars
and buses?

3 ways
How many ways to arrange cars?

• So if we have 4 parking spaces, how many different ways can we park cars
and buses?

5 ways
How many ways to arrange cars?

• 5 parking spaces?
• 6 parking spaces? #parking spaces #ways
0 1
1 1
2 2
3 3
4 5
5 8
6 13

• Can you figured out THE pattern?


 1, 1, 2, 3, 5, 8, 13, …
 What is the next number?
How many ways to arrange cars?

• In general, if we have n parking spaces, how many ways can we park


the vehicles?
• You can think backward, the last parking space can be either a car or
a bus

• If it’s a car, there are n - 1 spaces left, you can have the number of way
for n - 1 spaces
 Otherwise, it’s the number of way for n - 2 spaces
• So
f (n) = f (n - 1) + f (n - 2) for f(0) = f(1) = 1
Fibonacci Numbers

• Fibonacci numbers are found in nature (sea-


shells, sunflowers, etc)
• http://www.maths.surrey.ac.uk/hosted-
sites/R.Knott/Fibonacci/fibnat.html
Challenge

• Write a fibonacci function that can compute f(n) for n > 1000
Google about Recursion

• Try to search these in Google:


 Do a barrel roll
 Askew
 Anagram
 Google in 1998
 Zerg rush
• More in Google Easter Eggs
IT5001 Software Development Fundamentals
5. Recursion Vs Iterations and Nested Functions
Sirigina Rajendra Prasad

1
Recursion vs Iteration
Reversing a String
• How about reversing a string? Of course, we can just use string slicing

• How about we write a function for it?


Reverse String (Iterative Version 1)

i l-i-1 s[l-i-1] output


0 4 e e
1 3 d ed
2 2 c edc
3 1 b edcb
4 0 a edcba
Reverse String (Iterative Version 1)

i l-i-1 s[l-i-1] output


0 4 e e
1 3 d ed
2 2 c edc
3 1 b edcb
4 0 a edcba
Reverse String (Iterative Version 1)

i l-i-1 s[l-i-1] output


0 4 e e
1 3 d ed
2 2 c edc
3 1 b edcb
4 0 a edcba
Reverse String (Iterative Version 1)

i l-i-1 s[l-i-1] output


0 4 e e
1 3 d ed
2 2 c edc
3 1 b edcb
4 0 a edcba
Reverse String (Iterative Version 2)

c output
a a
b ba
c cba
d dcba
e edcba
Reversing String (Recursive Version)

• reverseStringR(‘abcde’)
• reverseStringR(‘bcde’)+’a’
• reverseStringR(‘cde’)+’b’+’a’
• reverseStringR(‘de’)+’c’+’b’+’a’
• reverseStringR(‘e’)+’d’+’c’+’b’+’a’
• reverseStringR(‘’)+’e’+’d’+’c’+’b’+’a’
• ‘’+’e’+’d’+’c’+’b’+’a’
• ‘edcba’
Taylor Series
Taylor Series

n=0 n=1 n=2


• We do not need the infinite precision
• We may just sum up to k terms
k
Computing sine by Iteration
k

• Using iteration

Python Library version of “sin()”


Computing sine by Recursion
Sum up to n = 2

Sum up to n = 1

• In general, if we want to sum up to the k terms


Sum up to n = k

k
kth

Sum up to n = k - 1
n=k
Computing sine by Recursion
• Assuming that if the function sinR(x,k) sums until n = k, then

sinR(x,k) = sinR(x,k-1) + the kth term

• In general, if we want to sum up to the k terms


Sum up to n = k

k
kth

Sum up to n = k - 1
n=k
Computing sine by Recursion
• Assuming that if the function sinR(x,k) sums until n = k, then
sinR(x,k) = sinR(x,k-1) + the kth term
More Taylor Series
Recursion Common Patterns

Base cases

Recursion step to reduce the problem one-by-one


Iteration Common Patterns

Accumulate element one-by-one

Initial the final answer to “nothing” at the beginning.


Accumulate and return the final answer
Iteration/Recursion Conversion

Base case The answer for previous k – 1 terms The kth term
Iteration/Recursion Conversion

Base case The answer for previous k – 1 terms The kth term
“Homework”

• The answer for all k-1 terms?


• Base case?
• Kth term?
Another Example
Recursion vs Iteration
• SumDigits
• Given a positive number 𝑛𝑛, the sum of all digits is obtained by adding the digit
one-by-one
• For example, the sum of 52634 = 5 + 2 + 6 + 3 + 4 = 20
• Write a function sum(n) to compute the sum of all the digits in n
• Factorial
• Factorial is defined (recursively) as 𝑛𝑛! = 𝑛𝑛 ∗ 𝑛𝑛 − 1 ! such that 0! = 1
• Write a function fact(n) to compute the value of n!

• Can you do it in both recursion and iteration?


SumDigits

Iteration Recursion
def sum(n): def sum(n):
res = 0 if n == 0:
while n > 0: return 0
res = res + n%10 else:
n = n//10 return n%10 + sum(n//10)
return res
base/initial value stop/base case (they are related, how?)
computation temporary result variables
continuation/next value not needed in recursion (why?)
Factorial

Iteration Recursion
def fact(n): def fact(n):
res = 1 if n == 0:
while n > 0: return 1
res = res * n else:
n = n-1 return n * fact(n-1)
return res
base/initial value stop/base case (they are related, how?)
computation temporary result variables
continuation/next value not needed in recursion (why?)
“Homework”
• How to re-write your code with both iterative/recursion version
mentioned in this course before?
• burgerPrice()
• checkAllAlpha()
• Etc.
• The answer for all k-1 terms?
• Base case?
• Kth term?
Code Refactoring
Code Refactoring
• Refactoring is a disciplined technique for restructuring an existing
body of code, altering its internal structure without changing its
external behavior.
Nested Functions
Nested Functions
• Functions defined inside other functions

x=2
inner_func
Namespace

x=2
enclosing_func Namespace

x=2 Global Namespace

Output: Builtin Namespace


Nested Functions
Namespace of inner function is different from enclosing function and global namespace

x=3
inner_func
Namespace

x=2
enclosing_func Namespace

x=2 Global Namespace

Builtin Namespace
Output:
Nested Functions
Inner functions can access global variables

inner_func
Namespace

enclosing_func Namespace

x=2 Global Namespace

Builtin Namespace
Output:
Nested Functions
Inner functions cannot modify global variables

x=?
inner_func
Namespace

enclosing_func Namespace

x=2 Global Namespace

Builtin Namespace
Nested Functions: global keyword
Modifying global variable from inner function
nonlocal/enclosing
namespace
for inner function

global keyword
inner_func
binds this variable to Namespace
global variable x x
enclosing_func Namespace

x Global Namespace

Builtin Namespace

Output:
Nested Functions
Inner functions can access nonlocal variables

inner_func
Namespace

x
enclosing_func Namespace

x Global Namespace

Builtin Namespace

Output:
Nested Functions
Inner functions cannot modify nonlocal variables

inner_func
Namespace

x
enclosing_func Namespace

x Global Namespace

Builtin Namespace

Output:
Nested Functions: nonlocal keyword
Names in enclosing_func namespace
are nonlocal variables for inner_func

Binds this name to variable


in nearest enclosing namespace

inner_func
Namespace
Output: x
enclosing_func Namespace

x=2
Global Namespace

Builtin Namespace
Nested Functions
enclosing function
for p1() and p3()

Inner function for


p1() and
enclosing function for p3()

Inner function for


p1() and p2()
Namespaces: Nested Functions

Global Namespace

Builtin Namespace

39
Namespaces: Nested Functions

x =3

Namespace of p1( )

Global Namespace

Builtin Namespace

40
Namespaces: Nested Functions

x=3
Namespace of p2( )
x=3
Namespace of p1( )

Global Namespace

Builtin Namespace

41
Namespaces: Nested Functions

x=3
output = 9

Namespace
of p3( )

x=3
Namespace of p2( )
x=3
Namespace of p1( )

Global Namespace

Builtin Namespace

42
Namespaces: Nested Functions

output = 9

x=3
Namespace of p2( )
x=3
Namespace of p1( )

Global Namespace

Builtin Namespace

43
Namespaces: Nested Functions

output = 9
x=3
Namespace of p1( )

Global Namespace

Builtin Namespace

44
Namespaces: Nested Functions

Global Namespace

Builtin Namespace

45
What is the output?
What is the output?
Where do we use inner functions?

• Higher-Order Functions (Week 5)


IT5001 Software Development Fundamentals
5. Recursion Vs Iterations and Nested Functions
Sirigina Rajendra Prasad

1
Recursion vs Iteration
Reversing a String
• How about reversing a string? Of course, we can just use string slicing

• How about we write a function for it?


Reverse String (Iterative Version 1)

i l-i-1 s[l-i-1] output


0 4 e e
1 3 d ed
2 2 c edc
3 1 b edcb
4 0 a edcba
Reverse String (Iterative Version 1)

i l-i-1 s[l-i-1] output


0 4 e e
1 3 d ed
2 2 c edc
3 1 b edcb
4 0 a edcba
Reverse String (Iterative Version 1)

i l-i-1 s[l-i-1] output


0 4 e e
1 3 d ed
2 2 c edc
3 1 b edcb
4 0 a edcba
Reverse String (Iterative Version 1)

i l-i-1 s[l-i-1] output


0 4 e e
1 3 d ed
2 2 c edc
3 1 b edcb
4 0 a edcba
Reverse String (Iterative Version 2)

c output
a a
b ba
c cba
d dcba
e edcba
Reversing String (Recursive Version)

• reverseStringR(‘abcde’)
• reverseStringR(‘bcde’)+’a’
• reverseStringR(‘cde’)+’b’+’a’
• reverseStringR(‘de’)+’c’+’b’+’a’
• reverseStringR(‘e’)+’d’+’c’+’b’+’a’
• reverseStringR(‘’)+’e’+’d’+’c’+’b’+’a’
• ‘’+’e’+’d’+’c’+’b’+’a’
• ‘edcba’
Taylor Series
Taylor Series

n=0 n=1 n=2


• We do not need the infinite precision
• We may just sum up to k terms
k
Computing sine by Iteration
k

• Using iteration

Python Library version of “sin()”


Computing sine by Recursion
Sum up to n = 2

Sum up to n = 1

• In general, if we want to sum up to the k terms


Sum up to n = k

k
kth

Sum up to n = k - 1
n=k
Computing sine by Recursion
• Assuming that if the function sinR(x,k) sums until n = k, then

sinR(x,k) = sinR(x,k-1) + the kth term

• In general, if we want to sum up to the k terms


Sum up to n = k

k
kth

Sum up to n = k - 1
n=k
Computing sine by Recursion
• Assuming that if the function sinR(x,k) sums until n = k, then
sinR(x,k) = sinR(x,k-1) + the kth term
More Taylor Series
Recursion Common Patterns

Base cases

Recursion step to reduce the problem one-by-one


Iteration Common Patterns

Accumulate element one-by-one

Initial the final answer to “nothing” at the beginning.


Accumulate and return the final answer
Iteration/Recursion Conversion

Base case The answer for previous k – 1 terms The kth term
Iteration/Recursion Conversion

Base case The answer for previous k – 1 terms The kth term
“Homework”

• The answer for all k-1 terms?


• Base case?
• Kth term?
Another Example
Recursion vs Iteration
• SumDigits
• Given a positive number 𝑛𝑛, the sum of all digits is obtained by adding the digit
one-by-one
• For example, the sum of 52634 = 5 + 2 + 6 + 3 + 4 = 20
• Write a function sum(n) to compute the sum of all the digits in n
• Factorial
• Factorial is defined (recursively) as 𝑛𝑛! = 𝑛𝑛 ∗ 𝑛𝑛 − 1 ! such that 0! = 1
• Write a function fact(n) to compute the value of n!

• Can you do it in both recursion and iteration?


SumDigits

Iteration Recursion
def sum(n): def sum(n):
res = 0 if n == 0:
while n > 0: return 0
res = res + n%10 else:
n = n//10 return n%10 + sum(n//10)
return res
base/initial value stop/base case (they are related, how?)
computation temporary result variables
continuation/next value not needed in recursion (why?)
Factorial

Iteration Recursion
def fact(n): def fact(n):
res = 1 if n == 0:
while n > 0: return 1
res = res * n else:
n = n-1 return n * fact(n-1)
return res
base/initial value stop/base case (they are related, how?)
computation temporary result variables
continuation/next value not needed in recursion (why?)
Towers of Hanoi Problem
• Move entire stack to the last
tower while obeying the
following rules
• Only one disc may be moved at a
time
• Each move consists of taking the
upper disk from one of the stacks
and placing it on top of another
stack or on an empty rod. https://en.wikipedia.org/wiki/Tower_of_Hanoi

• No disk may be placed on top of a


disk that is smaller than it.
Question: How many moves for 𝑛𝑛 discs?
2𝑛𝑛 − 1
Towers of Hanoi
S A D

Solution:
S A D

Towers of Hanoi Move three discs from source tower to


destination tower using auxiliary tower

Move(3,S,D,A) 1
Move two discs from auxiliary tower to
Move two discs from source tower to destination tower using source tower
auxiliary tower using destination tower

Move Disc 3 from


Move(2,S,A,D) 2 S to D
Move(2,A,D,S) 5
Move one disc from source
Move one disc from
tower to destination tower
destination tower to auxiliary
using auxiliary tower
tower using source tower
Move Disc 2 Move Disc 2
Move(1,S,D,A) 3 from S to A
Move(1,D,A,S) 4 Move(1,A,S,D) 6 from A to D
Move(1,S,D,A) 7

Move Disc 1 Move Disc 1 Move Disc 1 Move Disc 1


from S to D from D to A from A to S from S to D
Base case Base case Base case Base case

Depth-first
In-order traversal
“Homework”
• How to re-write your code with both iterative/recursion version
mentioned in this course before?
• burgerPrice()
• checkAllAlpha()
• Etc.
• The answer for all k-1 terms?
• Base case?
• Kth term?
Code Refactoring
Code Refactoring
• Refactoring is a disciplined technique for restructuring an existing
body of code, altering its internal structure without changing its
external behavior.
Nested Functions
Nested Functions
• Functions defined inside other functions

x=2
inner_func
Namespace

x=2
enclosing_func Namespace

x=2 Global Namespace

Output: Builtin Namespace


Nested Functions
Namespace of inner function is different from enclosing function and global namespace

x=3
inner_func
Namespace

x=2
enclosing_func Namespace

x=2 Global Namespace

Builtin Namespace
Output:
Nested Functions
Inner functions can access global variables

inner_func
Namespace

enclosing_func Namespace

x=2 Global Namespace

Builtin Namespace
Output:
Nested Functions
Inner functions cannot modify global variables

x=?
inner_func
Namespace

enclosing_func Namespace

x=2 Global Namespace

Builtin Namespace
Nested Functions: global keyword
Modifying global variable from inner function
nonlocal/enclosing
namespace
for inner function

global keyword
inner_func
binds this variable to Namespace
global variable x x
enclosing_func Namespace

x Global Namespace

Builtin Namespace

Output:
Nested Functions
Inner functions can access nonlocal variables

inner_func
Namespace

x
enclosing_func Namespace

x Global Namespace

Builtin Namespace

Output:
Nested Functions
Inner functions cannot modify nonlocal variables

inner_func
Namespace

x
enclosing_func Namespace

x Global Namespace

Builtin Namespace

Output:
Nested Functions: nonlocal keyword
Names in enclosing_func namespace
are nonlocal variables for inner_func

Binds this name to variable


in nearest enclosing namespace

inner_func
Namespace
Output: x
enclosing_func Namespace

x=2
Global Namespace

Builtin Namespace
Nested Functions
enclosing function
for p1() and p3()

Inner function for


p1() and
enclosing function for p3()

Inner function for


p1() and p2()
Namespaces: Nested Functions

Global Namespace

Builtin Namespace

42
Namespaces: Nested Functions

x =3

Namespace of p1( )

Global Namespace

Builtin Namespace

43
Namespaces: Nested Functions

x=3
Namespace of p2( )
x=3
Namespace of p1( )

Global Namespace

Builtin Namespace

44
Namespaces: Nested Functions

x=3
output = 9

Namespace
of p3( )

x=3
Namespace of p2( )
x=3
Namespace of p1( )

Global Namespace

Builtin Namespace

45
Namespaces: Nested Functions

output = 9

x=3
Namespace of p2( )
x=3
Namespace of p1( )

Global Namespace

Builtin Namespace

46
Namespaces: Nested Functions

output = 9
x=3
Namespace of p1( )

Global Namespace

Builtin Namespace

47
Namespaces: Nested Functions

Global Namespace

Builtin Namespace

48
What is the output?
What is the output?
Where do we use inner functions?

• Higher-Order Functions (Week 5)


Bugs and debugging
The Very First Obstacle of Programming
• Syntax Error
• A syntax error is an error in the
source code of a program.
Since computer programs
must follow strict syntax to
compile correctly, any aspects
of the code that do not
conform to the syntax of the
programming language will
produce a syntax error.
Sometime Errors are Fatal
• https://www.youtube.com/watch?v=VjJgiDuHlRw
Bugs?
• In 1947, Grace Murray Hopper
was working on the Harvard
University Mark II Aiken Relay
Calculator (a primitive
computer).

• On the 9th of September, 1947,


when the machine was
experiencing problems, an
investigation showed that there
was a moth trapped between
the points of Relay #70, in Panel
F.
Mark I
Bugs?
• The operators removed the moth and affixed it to the log. (See the
picture.) The entry reads: "First actual case of bug being found."
Humans make mistakes
You are only human
Therefore, you will make mistakes
Debugging
Debugging
• Means to remove errors (“bugs”) from a program.
• After debugging, the program is not necessarily error-free.
• It just means that whatever errors remain are harder to find.
• This is especially true for large applications.
W02 debug1.py
1

Fail!

3
4

Traceback (most recent call last):


1 File "<pyshell#0>", line 1, in <module>
p1(1,2)
2 File "C:\Users\dcschl\Google Drive\Courses\IT1007\Lectures\W02 debug 1.py",
line 3, in p1
b = p3(x,y)
3 File "C:\Users\dcschl\Google Drive\Courses\IT1007\Lectures\W02 debug 1.py",
line 10, in p3
return p2(a) + p2(b)
4 TypeError: p2() missing 1 required positional argument: 'w'
The IDLE Debugger
Using the IDLE Debugger
• Load in your source code
• Turn on the debugger by
The Debugger Window Pops up
Using the IDLE Debugger
• Go to your source code window to “run”
• Then the debugger will pause the program at the first line of code and
wait for you
• You can click the button “Go”
• That will make the program run
• At this point we don’t have any error
• Because by “running” the code, we just define the three functions
Using the IDLE Debugger
• Let’s execute the function in debug mode
• In the shell, type
p1(1,2)
• Then the debugger will pause at the first line of p1
• If you type “go” now, you will get an error like the last time
Using the IDLE Debugger
• Go
• Clicking this will run the program until the next break point is reached. You can insert break points
in your code by right clicking and selecting Set Breakpoint. Lines that have break points set on
them will be highlighted in yellow.
• Step
• This executes the next statement. If the statement is a function call, it will enter the function and
stop at the first line.
• Over
• This executes the next statement just as Step does. But it does not enter into functions. Instead, it
finishes executing any function in the statement and stops at the next statement in the same
scope.
• Out
• This exits the current function and stops in the caller of the current function.
• After using Step to step into a function, you can use Out to quickly execute all the statements in
the function and get back out to the outer function.
• Quit: This terminates execution.
Using the IDLE Debugger
• Currently in line 1
• Click “Step” goes
to line 2
Using the IDLE Debugger
Current position

Step: Go into functions, otherwise “over”

Out: run until


Over: run until next line
the current
function ends
More Debugging (BuggyAddNum)
Turn on Debugger
• After a few steps
Using the IDLE Debugger
Another Debugger: pythontutor.com
Common Types of Errors
Common Types of Errors
• Omitting return statement
def square(x):
x * x # no error msg!
• Incompatible types
x = 5
def square(x):
return x * x
x + square
• Incorrect # args
square(3,5)
Common Types of Errors
• Syntax
def proc(100)
do_stuff()
more()
• Arithmetic error
x = 3
y = 0
x/y
• Undeclared variables
x = 2
x + k
Common Types of Errors
• Infinite loop (from bad inputs)
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n-1)

fact(2.1)
fact(-1)
Common Types of Errors
• Infinite loop (forgot to decrement)
def fact_iter(n):
counter, result = n, 1
while counter!= 0:
result *= counter
return result
Common Types of Errors
• Numerical imprecision counter never exactly equals n
def foo(n):
counter, result = 0,0
while counter != n:
result += counter
counter += 0.1
return result

foo(5)
Common Types of Errors
• Logic
def fib(n):
if n < 2:
return n
else:
return fib(n-1) + fib(n-1)
How to debug?
• Think like a detective
• Look at the clues: error messages, variable values.
• Eliminate the impossible.
• Run the program again with different inputs.
• Does the same error occur again?
How to debug?
• Work backwards
• From current sub-problem backwards in time
• Use a debugger
• IDLE has a simple debugger
• Overkill for our class
• Trace a function
• Display variable values
Displaying variables
debug_printing = True
def debug_print(msg):
if debug_printing:
print(msg)

def foo(n):
counter, result = 0,0
while(counter != n):
debug_print(f'{counter}, {n}, {result}')
counter, result = counter + 0.1, result + counter
return result
Example
def fib(n):
debug_print(f'n:{n}')
if n < 2:
return n
else:
return fib(n-1) + fib(n-1)
Other tips
• State assumptions clearly.

def factorial(n): # n integer >= 0


if n == 0:
return 1
else:
return n * factorial(n-1)

• Test each function before you proceed to the next.


• Remember to test boundary cases
Summary
• Compound data helps us to reason at a higher conceptual level.
• Abstraction barriers separate usage of a compound data from its
implementation.
• Only functions at the interface should be used.
• We can choose between different implementations as long as
contract is fulfilled.
Debugging is an Art
Maths vs CS vs Engineering
• Three good friends, an engineer, a mathematician and a
computer scientist, are driving on a highway that is in the
middle of no where. Suddenly one of the tires went flat and
they have no spare tire.
Maths vs CS vs Engineering
• Engineer
• “Let’s use bubble gum to patch the tire and use the strew to inflate
it again”
• Mathematician
• “I can prove that there is a good tire exists in somewhere this
continent”
• Computer Scientist
• “Let’s remove the tire, put it back, and see if it can fix itself again”
Data Collections
(Sequences)
It’s complicated
Sequence in Python
• Indexed collection
– Strings
– Lists
– Tuples

• Non-indexed collection:
– Sets
– Dictionary
Lists and Tuples
• Belongs to a type of data structure called arrays

• Intrinsic ordering
– Easy to retrieve data from the array

• Lists
– Mutable
– Dynamic Arrays

• Tuples
– Immutable
– Static Arrays
3
Lists
• Ordered sequence of data types
– Homogeneous sequence
• Sequence of integers
• Sequence of floats
• Sequence of strings
• Sequence of lists
• Sequence of functions, etc.
– Heterogeneous sequence
• mix of integers, floats, strings, etc.

• Defined using square brackets - [ ]

4
Lists are Referential Arrays

Lists store addresses of its items in sequence

5
All Indexed Sequences can…
a[i] return i-th element of a
a[i:j] returns elements i up to j-1
len(a) returns numbers of elements in sequence
min(a) returns smallest value in sequence
max(a) returns largest value in sequence
x in a returns True if x is a part of a
a + b concatenates a and b
n * a creates n copies of sequence a
Lists are mutable
• Elements can be replaced
• Elements can be added
• Elements can be removed
– A specific element
• If element occurs multiple times, removes first occurrence
– Element at a specific location (index)
– From the end of the list
• Elements can be sorted
– sort()
– Sorted()
• Elements can be reversed

8
Lists are Dynamic-Size Arrays
Elements can be added (appended) Elements can be removed
to the list from the list

9
Append Vs Concatenation
1

10
Append Vs Concatenation

11
Append Vs Concatenation
Strings to Lists and Vice-Versa

13
Strings to Lists and Vice-Versa

14
Aliasing vs Cloning
Aliasing

15
Aliasing vs Cloning

Cloning

16
Sort vs Sorted
• sort() method mutates the list

• sorted() method creates a new sorted list without mutating the original list

17
Reverse
• reverse() method mutates the list

18
Lists of Anything
• A list of ….
– Lists?
Block Diagram

list1 list2

[] []

1 2 2 ‘a’ ‘b’ ‘c’


Block Diagram

list3

[]

[] []

1 2 2 ‘a’ ‘b’ ‘c’


Lists are Iterable
due to this method

22
For loop
>>> for i in range(0,5): >>> for i in [0,1,2,3,4]:
print (i) print(i)

0 0
1 1
2 2
3 3
4 4
For Loop

Output:
Never do this

Why?

25
Mutation and Iteration
• Avoid mutating a list while iterating over the list

• next() method uses an index to retrieve the


elements from myList
• remove() method mutates the myList, but the
index in next() method will not be updated

26
Example: Find Max in A List of No.

• Is there any potential problem?


Example: Find all Even Numbers
List Comprehensions
• Provides a concise way to apply an operation
to the items in iterable object and store the
result as a list

• Syntax:
– [expr for elem in iterable if test]

• Returns an iterable
29
List Comprehension
• Todo:
– create a list:
a_list = [1,2,3,4,5,6,…… , 100]
• You can
List Comprehension
The item really in the list
• Or every i between 1 and
101 (exclusive)

Compare to
𝑏𝑏 = {𝑖𝑖|𝑖𝑖 ∈ 1,101 } ordinary math
equation
List Comprehension
• How do I produce a list of first 10 squared
numbers?

Compare to
𝑏𝑏 = {𝑖𝑖 2 |𝑖𝑖 ∈ 1,101 } ordinary math
equation
List Comprehension
• How do I produce a list of odd numbers less
than 100 Stop (exclusive)
Step
Start
– Like string slicing
List Comprehension
• How do I produce a list of even numbers less
than 100
– Similar to the previous one but start with 2
– Or
Advance: Generate Prime Numbers
• Let’s generate all the prime numbers < 50
• First, generate all the non-prime numbers <50
i is from 2 to 7 get all the multiples of i
(7 = sqrt(50)) from 2*i to 49
Advance: Generate Prime Numbers
• Let’s generate all the prime numbers < 50
• First, generate all the non-prime numbers <50
i is from 2 to 7 get all the multiples of i
from 2*i to 49

i=2 i=3 i=4


Generate Prime Numbers
• Let’s generate all the prime numbers < 50
• First, generate all the non-prime numbers <50
• Prime numbers are the numbers NOT in the
list above
Generator Expressions
• Provides a generator that can be used to iterate over
without explicitly generating the list of items

• Syntax:
– (expr for elem in iterable if test)

• Returns an iterator

• Requires less memory than list


– Check!

38
Generator Expressions

Output:

Which is better?
Generator Expressions

Output:

40
Sequence in Python
• Indexed collection
– Strings
– Lists
– Tuples

• Non-indexed collection:
– Sets
– Dictionary
Tuples
• A static and an immutable array/list
Task Syntax
Return i-th element a[i]

• Syntax: Return elements from i to j-1 a[i:j]

Return number of elements len(a)


– int_tuple = (1,2,3) Return smallest value in sequence min(a)

– float_tuple = (1.0,2.0,3.0) Return largest value in sequence max(a)

– str_tuple = (‘hi’,’IT5001’) Returns if an element is part of sequence x in a

Concatenates two sequences a+b


– mixed_tuple = (1,1.0,’IT5001’)Creates n copies of a sequence a*n

42
Tuples: Example 1

43
Tuples: Example 2

Immutable:
creates a new tuple – but not assigned

44
Tuples: Example 2

Old tuple is unchanged

Creates a new tuple and assigned to integer_tuple_1


45
Lists and Tuples
• Similarities:
– List and Tuple are
• Indexed
• Iterable
– Both can store heterogeneous data types

• Differences:
– List is mutable
– Tuple is immutable
46
Tuple
• A Tuple is basically a list but
– CANNOT be modified
Tuples use ‘(‘ and ‘)’
Lists use ‘[‘ and ‘]’
Tuple
• A Tuple is basically a list but
– CANNOT be modified
For a Singleton of List and Tuple…

• a list with only one • a tuple with only one


element element

!!!
A Tuple with only one element
• Correct way

Note the
comma
here
But then, why use Tuple? Or List?

Or when to use Tuple? When to use


List?
English Grammar
• Which sentence is grammatically correct?
– “I have more than one fish. Therefore, I have
many fish”
– “I have more than one fish. Therefore, I have
many fishes”

• Both of them are grammatically correct!


– But they mean different things
Fish vs Fishes
• The plural of fish is usually fish.
• When referring to more than one species of
fish, especially in a scientific context, you can
use fishes as the plural.
List vs Tuple, Cultural Reason
• List
– Usually stores a large collection of data with the
same type (homogenous)
– E.g. List of 200 student names in a class
• Tuple
– Usually stores a small collections of items with
various data types/concepts (heterogeneous )
– E.g. A single student record with name (string),
student number(string) and mark(integer)
But, violating this “culture” will NOT cause any syntax error
An Example
• To store the data on a map
– These are the locations of 100 nice restaurants in
Singapore
– The location of each restaurant is recorded as the
coordinates value of x and y
• (100,50)
• (30, 90)
• (50, 99)
• etc…
An Example
• I will code like this

• Is it
1. a tuple of tuples,
2. a tuple of lists,
3. a list of tuples, or
4. a list of lists?
Find all the restaurants near me
• I will code like this

shortened the name


Just a fake function
to generate the list
for this demo

A list

A tuple
Challenge:
Find the nearest THREE restaurants
Instead of ALL
List vs Tuple, Cultural Reason
• List
– Usually stores a large collection of data with the
same type (homogenous)
– E.g. List of 200 student names in a class
• Tuple
– Usually stores a small collections of items with
various data types/concepts (heterogeneous )
– E.g. A single student record with name (string),
student number(string) and mark(integer)
But, violating this “culture” will NOT cause any syntax error
List vs Tuple, Technical Reasons
• Immutable vs
mutable
– Tuple is Write
protected
(Immutable)

• List can be changed


within a function
– NOT passed by value
– Mutable
Recap: Primitive Data Types
• The print () in
“changeValue” will
print 999
• But how about the last
print(x)?
– Will x becomes 999?

• (So actually this


function will NOT
change the value of x)
Recap: Primitive Data Types
• n is another copy of x
• You can deem it as

Pass By Values
But for List
• Mutable!

!!!
Sequence in Python
• Indexed collection
– Strings
– Lists
– Tuples

• Non-indexed collection:
– Sets
– Dictionary
Sets
• A set is an unordered collection of immutable
elements with no duplicate elements
– Unordered: You cannot get a single element by its
index like s[2]
– No duplicate: every element exists only once in a
set

Python
Tuples use ‘(‘ and ‘)’ Removes
Lists use ‘[‘ and ‘]’ duplicates
Sets use ‘{‘ and ‘}’ for you
Sets
• Some operations are not available because
sets are NOT indexed
a[i] return i-th element of a
a[i:j] returns elements i up to j-1
len(a) returns numbers of elements in sequence
min(a) returns smallest value in sequence
max(a) returns largest value in sequence
x in a returns True if x is a part of a
a + b concatenates a and b
n * a creates n copies of sequence a
Set Operations
• Intersection • A–B

• Union • Symmetric Difference


Sets
• Usual set operations

Union

Intersection

A-B

(A | B) – A & B
Sets
Remove like a list

But error if element missing

But we can use


discard instead
Sets are Iterable
Set from List and Vice-Versa
Sequence in Python
• Indexed collection
– Strings
– Lists
– Tuples

• Non-indexed collection:
– Sets
– Dictionary
Dictionary Word

Its meaning

Word

Its meaning
Dictionary
• You search for the word in the dictionary
• Then look for its meaning

Word Meaning
• Each word has a correspondent meaning
Python Dictionary
• You search for the key in the dictionary
• Then look for its value

Key Value
• Each key has a correspondent value key : value
pair

Tuples use ‘(‘ and ‘)’


Lists use ‘[‘ and ‘]’
Sets and Dict use ‘{‘ and ‘}’
An Example
• To store the data on a map
– These are the locations of 100 nice restaurants in
Singapore
– The location of each restaurant is recorded as the
coordinates value of x and y and name
– (10,20):Pizza Hut
Python Dictionary
• Key: location
• Value: restaurant name
• After you searched for the nearest
restaurants, you want to know their names
Recap: List
• Or tuples

Index:
From 0 to len(a)-1

Input a number Output an item


But when you go to Japan
• You are not inputting a number (index)!

Input a number a name

Output an item
To set up a dictionary
• Each pair has a key and a value

key value key value


What is Dictionary?
• Key is on the left, Value on the right

• Summary: A data structure used for


“When I give you X, give me Y”
• Can store any type
• Called HashTable in some other languages
How is a Dictionary Useful?
• Keep Track of Things by Key!
– Eg, keeping track of stocks of fruits

my_stock = {“apples”:450”,”oranges”:412}
my_stock[“apples”]
>>> 450

my_stock[“apples”] + my_stock[“oranges”]
>>> 862
How is a Dictionary Useful?

• Keep Track of Things by Key!


– When you want to get an associated operation
(eg, alphabets to numeric integers)

my_alphabet_index = {‘a’:1,’b’:2… ‘z’:26}


my_alphabet_index[‘z’]
>>> 26
Dictionary Methods
• Access (VERY FAST! - Almost instant!)
• Assignment
• Removal
• Other Dictionary Methods
Dictionary Access
>>> my_fruit_inventory = {“apples”:450,”oranges”:200}
>>> my_fruit_inventory[“apples”]
450
>>> my_fruit_inventory.get(“apples”)
450
>>> my_fruit_inventory[“pears”]
KeyError!
>>> my_fruit_inventory.get(“pears”)
None

**Cannot access keys which don’t exist!**


• Accessing with [] will crash if does not exist
• Accessing with .get() will NOT crash if key does not exist
Dictionary Assignment
>>> my_fruit_inventory[“pears”] = 100
>>> print(my_fruit_inventory)
{“apples”:450, ”oranges”:200, “pears”:100}

• Caution: This OVERWRITES existing values!


>>> my_fruit_inventory[“oranges”] = 100
>>> print(my_fruit_inventory)
{“apples”:450, ”oranges”:100, “pears”:100}
Dictionary Removal
>>> my_fruit_inventory =
{“apples”:450,”oranges”:200}

>>> my_fruit_inventory.pop(“apples”)
>>> print(my_fruit_inventory)
{‘oranges’:200}

• OR

>>> del my_fruit_inventory[“apples”]


Other Dictionary Methods
.clear() • clear all
.copy() • make a copy
.keys() • return all keys
.values() • return all values
.items() • return all keys + values
Dictionary is Iterable
Sequence in Python
• Indexed
– Strings
– Lists
– Tuples

• Non-indexed collection:
– Sets
– Dictionary
IT5001 Software Development Fundamentals

8. Sequences Contd.
Sirigina Rajendra Prasad

1
Python: Hashability and Immutability
Hashable

Data Type Immutable Hashable


Integer Yes Yes Immutable
Float Yes Yes
String Yes Yes Strings
Tuple Yes Yes Int
List No No Float
Tuple
Set No No
Dictionary No No

All immutable objects are Hashable but not vice-versa

2
Returning Multiple Values

Treated as a tuple

Unpacking of tuple

Output:
If you don’t know number of arguments
Unknown number of positional arguments

Output:
If you don’t know number of arguments
Unknown number of keyword arguments

Output:
Accessing Global Variables
• Can a function access (read) a global variable?
• Variable is Immutable
• Yes
• Variable is Mutable
• Yes

Output:

6
Modifying Global Variables
• Can a function modify a global variable with variable declared global within
local function?
• Yes, for both mutable and immutable variables

Output:

7
Modifying Global Variables
• Can a function modify a global variable with variable not declared as global
within local function?
• No, for immutable variables
• Yes, for mutable variables with only the methods that mutate data (append, sort, etc.)

No assignment to variable 𝑥𝑥
Output:

8
Scope
• Passing a mutable variable as argument

Output:
How are arguments passed to functions?
• Pass-by-Value
• An independent (duplicate) copy of argument
argument is passed as input
• Not good if the argument size is very large
• Requires additional memory and execution time 0x0001 2

address
• Pass-by-Reference
• Address of argument is passed and function
access the value from address
• Efficient for arguments of very large size
How about Python?

• Pass-by-Value or Pass-by-Reference?
• Neither of them

• Python passes objects by assignment


• Pass-by-Assignment

• Only exception is with global keyword


With global keyword

equivalent to pass-by-reference
Pass-by-Assignment
• Best Practice
• Pass value by assignment, modify, and reassign
Pass-by-Assignment
• For mutable variables

Effect is similar to pass-by-value Effect is similar to pass-by-reference


Scope: Summary
• Parameter Passing
• Pass-by-Assignment

• Immutable Variable
• Can access global variable
• Cannot modify global variable unless declared global

• Mutable Variable
• Can access global variable
• Can modify the variable
• Need to use global keyword for methods that do not mutate objects
• No need of global keywords for methods that mutate objects

15
How are lists resized with append?

Ternary operator in C

additional_allocated = current_size >>3 + current_size < 9 ? 3 : 6

floored-division by 8
if current_size < 9:
𝑐𝑐𝑐𝑐𝑐𝑐𝑐𝑐𝑐𝑐𝑐𝑐𝑐𝑐_𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠 3
else:
8
6

16
How are lists resized Appending 5th element:
Leads to allocation of space for 3 more elements

with append?
Space of 8 elements is reserved for list
No need to create additional space till list is filled
Empty list

Appending 1st element:


Leads to allocation of space for 4 elements
Space of 4 elements is reserved for list
No need to create additional space till list is filled

Appending 17th element:


Leads to allocation of space for 8 (= 2+6) more elements
Space of 25 elements is reserved for list
No need to create additional space till list is filled

Appending 9th element:


leads to allocation of space for 7 more elements
Space of 16 elements is reserved for list
No need to create additional space till list is filled

17
How are lists resized with append?

18
How are lists resized with concatenation?
• Always create a new list
• Copies the contents of old list and new list combined

New element
List Append Vs Concatenation
List Append Vs Concatenation

Concatenation is slow as it creates new


list for every new concatenation
List Append Vs Tuple Concatenation

Modifying tuple is slow as it creates new


tuple for every new concatenation
Insertion/Deletion in lists?

0
1
2 Inserting of new element or
Deletion of an element
3 leads to to relocation of
4 elements in subsequent indices

5
6
7

23
List Vs Tuple: Conclusion

Tuple Version List Version


• Preserve input • May or may not preserve input
• May modify input
• Must return result • May or may not need to return result

• Slower • Faster (append)

• Slower (concatenation)
Miscellaneous
Dictionary – Bucket Array
𝐴𝐴(ℎ(𝑘𝑘)) = 𝑣𝑣
Key (𝑘𝑘) is mapped to an index (0 to N-1) and Value (𝑣𝑣) is stored in the corresponding bucket

Index 0 1 2 3 N-3 N-2 N-1

Key to index mapping is done through Hash Function (ℎ(𝑘𝑘))

https://research.cs.vt.edu/AVresearch/hashing/index.php 26
Hash Function - ℎ(𝑘𝑘)
Keys Index
Objects

ℎ 𝑘𝑘

Integer within a range


[0, 𝑁𝑁 − 1]

27
Hash Function - ℎ(𝑘𝑘)
Objects

Objects
Stage 1: Hash Code

implemented Integers
ℎ 𝑘𝑘 in two stages … , −2, −1,0,1,2, …

Stage 2: Compression Function


Integer within a range
[0, 𝑁𝑁 − 1]
Integer within a
range
[0, 𝑁𝑁 − 1]

28
Hash Code
• Bit representation as hash codes

• Polynomial hash codes


• 𝑥𝑥0 𝑎𝑎𝑛𝑛−1 + 𝑥𝑥1 𝑎𝑎𝑛𝑛−2 + ⋯ + 𝑥𝑥𝑛𝑛−2 𝑎𝑎+ 𝑥𝑥𝑛𝑛−1
• 𝑥𝑥𝑖𝑖 ∶ Coefficients
• 𝑎𝑎 : Constant

• Cyclic-shift hash codes

29
Compression Functions
• Division Method 𝑖𝑖 𝑚𝑚𝑚𝑚𝑚𝑚 𝑁𝑁

• Multiply-Add-and-Divide (MAD) Method

𝑎𝑎𝑎𝑎 + 𝑏𝑏 𝑚𝑚𝑚𝑚𝑚𝑚 𝑝𝑝 𝑚𝑚𝑚𝑚𝑚𝑚 𝑁𝑁

30
Collisions Collision occurs if multiple keys produce same hash value

ℎ(𝑘𝑘1 ) = ℎ(𝑘𝑘2 )

0 1 2 3 N-3 N-2 N-1

31
Collision-Handling
• Separate Chaining

• Open Addressing
• Linear Probing
• Quadratic Probing
• Double Hashing

32
Collision-Handling
• Separate Chaining
0 1 2 3 N-3 N-2 N-1

• Each bucket contains a list of values 𝑣𝑣𝑖𝑖 whose ℎ(𝑘𝑘𝑖𝑖 ) are same
 Requires additional list data structure
 Slows down the access as the list need to be searched for the key

33
Open Addressing
• Linear Probing

• Quadratic Probing

• Double Hashing

34
IT5001 Software Development
Fundamentals

8. Anonymous Functions
Sirigina Rajendra Prasad

1
Functions

• Traditional Form
 square(𝑥𝑥) ↦ 𝑥𝑥 2

• Anonymous Form:
 𝑥𝑥 ↦ 𝑥𝑥 2

2
Anonymous Functions

• Also known as lambda (𝜆𝜆) functions


 Functions without name

• Python Syntax:
 lambda args: expression

3
Functions: Traditional Maths vs 𝜆𝜆-Calculus

Mathematics 𝜆𝜆-Calculus
• Abstraction • Abstraction
• 𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠: 𝑥𝑥 ↦ 𝑥𝑥 2 • 𝑥𝑥 ↦ 𝑥𝑥 2
• 𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠 𝑥𝑥 = 𝑥𝑥 2 • 𝜆𝜆𝜆𝜆. 𝑥𝑥 2

• Application • Application
• 𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠 5 = 52 = 25 • (𝜆𝜆𝜆𝜆. 𝑥𝑥 2 )5 = 52 = 25

4
Functions: 𝜆𝜆-Calculus vs Python

𝜆𝜆-Calculus Python
• Abstraction • Abstraction
• 𝑥𝑥 ↦ 𝑥𝑥 2
• 𝜆𝜆𝜆𝜆. 𝑥𝑥 2

• Application • Application
• (𝜆𝜆𝜆𝜆. 𝑥𝑥 2 )5 = 52 = 25

or Abstraction

Application

5
Examples: Identity Function

𝜆𝜆-Calculus Python
• 𝜆𝜆-Calculus
• 𝜆𝜆𝜆𝜆. 𝑥𝑥
• Takes a variable
𝑥𝑥 as input argument
• returns 𝑥𝑥

6
Examples: Constant Function

𝜆𝜆-Calculus Python
• 𝜆𝜆-Calculus
• 𝜆𝜆𝜆𝜆. 𝑦𝑦
• Takes a variable 𝑥𝑥 and
return 𝑦𝑦

Alternative in Python:

7
Anonymous Functions: More Examples

• Can pass multiple arguments as inputs

8
IT5001 Software Development
Fundamentals

9a. Higher Order Functions

1
Functions in Python

• Functions can be
 Assigned to variables

 Passed as arguments to functions

 Returned from functions

2
“Callability”

• Normal variables are NOT callable

• A function is callable

3
Assignments

• Normal variables can store values

• Can a variable store a function?!

• Can!!!!!!
4
Assignments

• The function f is stored in the variable x


 So x is a function, same as f

5
See the difference

With ‘()’ Without ‘()’

values

types

6
Assigning to a variable

Output:

7
Functions can be stored in variables

Equivalent
to cos(0)

The type is
“function”

8
Functions as elements in Lists/Tuples

Output:

Output:

9
Functions as elements in Dictionaries

function as key

10
Functions as input arguments
Function calling
other function

Nested function

Function as input argument

Output:
11
Functions that return functions

• Functions can return inner functions as output

• Inner functions serves many purposes

 Closures

 Decorators

12
Closures

• Closure:
 Returns inner functions
 Function plus the environment (state) in which they execute together
 Preserve function state across function calls

• Example:
Access to variable
from outer function

Returns inner function

13
Closures

• Create Functions to Power a Number

14
Decorators

• Decorator is a closure
 Additionally, outer function accepts a function as input argument

• Modify input function’s behaviour with an inner function without explicitly


changing input function’s code

• Example

15
Function Composition

• In math, we can do something like


log(sin 𝑥𝑥 )

Equivalent to

16
Mix and Match
A function
A variable
(can be a
function
too!)

Equivalent to

17
Examples

18
The “Powerful” Lambda

19
Agar Agar (Anyhow) Derivative

• We know that, given a function f, the derivative of f is

𝑑𝑑𝑑𝑑(𝑥𝑥) 𝑓𝑓 𝑥𝑥 + ∆𝑥𝑥 − 𝑓𝑓(𝑥𝑥)


= lim
𝑑𝑑𝑑𝑑 ∆𝑥𝑥→0 ∆𝑥𝑥

• But, if we have very small number dx

𝑑𝑑𝑑𝑑(𝑥𝑥) 𝑓𝑓 𝑥𝑥 + 𝑑𝑑𝑑𝑑 − 𝑓𝑓(𝑥𝑥)



𝑑𝑑𝑑𝑑 𝑑𝑑𝑑𝑑

20
Agar Agar (Anyhow) Derivative

• We know that, given a function f, the derivative of f is

𝑑𝑑𝑑𝑑(𝑥𝑥) 𝑓𝑓 𝑥𝑥 + ∆𝑥𝑥 − 𝑓𝑓(𝑥𝑥)


= lim
𝑑𝑑𝑑𝑑 ∆𝑥𝑥→0 ∆𝑥𝑥

𝑑𝑑 sin 𝑥𝑥
• = cos 𝑥𝑥
𝑑𝑑𝑑𝑑

𝑑𝑑 (𝑥𝑥 3 +3𝑥𝑥−1)
• = 3𝑥𝑥 2 + 3
𝑑𝑑𝑑𝑑

21
Agar Agar (Anyhow) Derivative

• We know that, given a function f, the derivative of f is

𝑑𝑑𝑑𝑑(𝑥𝑥) 𝑓𝑓 𝑥𝑥 + ∆𝑥𝑥 − 𝑓𝑓(𝑥𝑥)


= lim
𝑑𝑑𝑑𝑑 ∆𝑥𝑥→0 ∆𝑥𝑥

𝑑𝑑 sin 𝑥𝑥
Derivatives cos 𝑥𝑥
𝑑𝑑𝑑𝑑

𝑑𝑑 (𝑥𝑥 3 + 3𝑥𝑥 − 1) Derivatives 3𝑥𝑥 2 + 3


𝑑𝑑𝑑𝑑

22
Agar Agar (Anyhow) Derivative

• Its input is a function


 And output another function

𝑑𝑑 sin 𝑥𝑥
Derivatives cos 𝑥𝑥
𝑑𝑑𝑑𝑑

𝑑𝑑 (𝑥𝑥 3 + 3𝑥𝑥 − 1) Derivatives 3𝑥𝑥 2 + 3


𝑑𝑑𝑑𝑑

23
Agar Agar (Anyhow) Derivative

• We know that, given a function f, the derivative of f is


𝑑𝑑𝑑𝑑(𝑥𝑥) 𝑓𝑓 𝑥𝑥 + ∆𝑥𝑥 − 𝑓𝑓(𝑥𝑥)
= lim
𝑑𝑑𝑑𝑑 ∆𝑥𝑥→0 ∆𝑥𝑥

• But, if we have very small number dx Take in a function,


𝑑𝑑𝑑𝑑(𝑥𝑥) 𝑓𝑓 𝑥𝑥 + 𝑑𝑑𝑑𝑑 − 𝑓𝑓(𝑥𝑥) returning another

𝑑𝑑𝑑𝑑 𝑑𝑑𝑑𝑑 function

24
Agar Agar (Anyhow) Derivative

• We know that, given a function f, the derivative of f is


𝑑𝑑𝑑𝑑(𝑥𝑥) 𝑓𝑓 𝑥𝑥 + ∆𝑥𝑥 − 𝑓𝑓(𝑥𝑥)
= lim
𝑑𝑑𝑑𝑑 ∆𝑥𝑥→0 ∆𝑥𝑥

• But, if we have very small number dx


𝑑𝑑𝑑𝑑(𝑥𝑥) 𝑓𝑓 𝑥𝑥 + 𝑑𝑑𝑑𝑑 − 𝑓𝑓(𝑥𝑥)

𝑑𝑑𝑑𝑑 𝑑𝑑𝑑𝑑

25
Agar Agar (Anyhow) Derivative

Take in a function,
returning another
function

26
Agar Agar (Anyhow) Derivative

𝑑𝑑 sin 𝑥𝑥
Derivatives cos 𝑥𝑥
𝑑𝑑𝑑𝑑

𝑑𝑑 (𝑥𝑥 3 + 3𝑥𝑥 − 1) Derivatives 3𝑥𝑥 2 + 3


𝑑𝑑𝑑𝑑

27
Application Example
of deriv()

28
Example: Newton’s method

• To compute root of function g(x), i.e. find x such that g(x) = 0

1. Anyhow assume the answer x = something


2. If g(x) ≈ 0 then stop: answer is x, return x
3. Otherwise
• x = x – g(x)/deriv(x)
4. Go to step 2

29
Example: Newton’s method

• To compute root of function g(x), i.e. find x such that g(x) = 0

1. Anyhow assume the answer x = something


2. If g(x) ≈ 0 then stop: answer is x, return x
3. Otherwise
• x = x – g(x)/deriv(x)
4. Go to step 2

30
Example: Newton’s method

• To compute the root of function g(x), i.e. find x such that g(x) = 0

31
Example: Newton’s method

• Example: Square root of a number A


 It’s equivalent to solve the equation: 𝑥𝑥 2 − 𝐴𝐴 = 0

32
Example: Newton’s method

• Example: Compute log10 (A)


 Solve the equation: 10𝑥𝑥 − 𝐴𝐴 = 0

33
34
You can solve any
equation!
…. that Newton Method can solve.

35
IT5001 Software Development
Fundamentals

9a. Higher Order Functions

1
Functions in Python

• Functions can be
 Assigned to variables

 Passed as arguments to functions

 Returned from functions

2
“Callability”

• Normal variables are NOT callable

• A function is callable

3
Assignments

• Normal variables can store values

• Can a variable store a function?!

• Can!!!!!!
4
Assignments

• The function f is stored in the variable x


 So x is a function, same as f

5
See the difference

With ‘()’ Without ‘()’

values

types

6
Assigning to a variable

Output:

7
Functions can be stored in variables

Equivalent
to cos(0)

The type is
“function”

8
Functions as elements in Lists/Tuples

Output:

Output:

9
Functions as elements in Dictionaries

function as key

10
Functions as input arguments
Function calling
other function

Nested function

Function as input argument

Output:
11
Functions that return functions

• Functions can return inner functions as output

• Inner functions serves many purposes

 Closures

 Decorators

12
Closures

• Closure:
 Returns inner functions
 Function plus the environment (state) in which they execute together
 Preserve function state across function calls

• Example:
Access to variable
from outer function

Returns inner function

13
Closures

• Create Functions to Power a Number

14
Decorators

• Decorator is a closure
 Additionally, outer function accepts a function as input argument

• Modify input function’s behaviour with an inner function without explicitly


changing input function’s code

• Example

15
Function Composition

• In math, we can do something like


log(sin 𝑥𝑥 )

Equivalent to

16
Mix and Match
A function
A variable
(can be a
function
too!)

Equivalent to

17
Examples

18
The “Powerful” Lambda

19
Agar Agar (Anyhow) Derivative

• We know that, given a function f, the derivative of f is

𝑑𝑑𝑑𝑑(𝑥𝑥) 𝑓𝑓 𝑥𝑥 + ∆𝑥𝑥 − 𝑓𝑓(𝑥𝑥)


= lim
𝑑𝑑𝑑𝑑 ∆𝑥𝑥→0 ∆𝑥𝑥

• But, if we have very small number dx

𝑑𝑑𝑑𝑑(𝑥𝑥) 𝑓𝑓 𝑥𝑥 + 𝑑𝑑𝑑𝑑 − 𝑓𝑓(𝑥𝑥)



𝑑𝑑𝑑𝑑 𝑑𝑑𝑑𝑑

20
Agar Agar (Anyhow) Derivative

• We know that, given a function f, the derivative of f is

𝑑𝑑𝑑𝑑(𝑥𝑥) 𝑓𝑓 𝑥𝑥 + ∆𝑥𝑥 − 𝑓𝑓(𝑥𝑥)


= lim
𝑑𝑑𝑑𝑑 ∆𝑥𝑥→0 ∆𝑥𝑥

𝑑𝑑 sin 𝑥𝑥
• = cos 𝑥𝑥
𝑑𝑑𝑑𝑑

𝑑𝑑 (𝑥𝑥 3 +3𝑥𝑥−1)
• = 3𝑥𝑥 2 + 3
𝑑𝑑𝑑𝑑

21
Agar Agar (Anyhow) Derivative

• We know that, given a function f, the derivative of f is

𝑑𝑑𝑑𝑑(𝑥𝑥) 𝑓𝑓 𝑥𝑥 + ∆𝑥𝑥 − 𝑓𝑓(𝑥𝑥)


= lim
𝑑𝑑𝑑𝑑 ∆𝑥𝑥→0 ∆𝑥𝑥

𝑑𝑑 sin 𝑥𝑥
Derivatives cos 𝑥𝑥
𝑑𝑑𝑑𝑑

𝑑𝑑 (𝑥𝑥 3 + 3𝑥𝑥 − 1) Derivatives 3𝑥𝑥 2 + 3


𝑑𝑑𝑑𝑑

22
Agar Agar (Anyhow) Derivative

• Its input is a function


 And output another function

𝑑𝑑 sin 𝑥𝑥
Derivatives cos 𝑥𝑥
𝑑𝑑𝑑𝑑

𝑑𝑑 (𝑥𝑥 3 + 3𝑥𝑥 − 1) Derivatives 3𝑥𝑥 2 + 3


𝑑𝑑𝑑𝑑

23
Agar Agar (Anyhow) Derivative

• We know that, given a function f, the derivative of f is


𝑑𝑑𝑑𝑑(𝑥𝑥) 𝑓𝑓 𝑥𝑥 + ∆𝑥𝑥 − 𝑓𝑓(𝑥𝑥)
= lim
𝑑𝑑𝑑𝑑 ∆𝑥𝑥→0 ∆𝑥𝑥

• But, if we have very small number dx Take in a function,


𝑑𝑑𝑑𝑑(𝑥𝑥) 𝑓𝑓 𝑥𝑥 + 𝑑𝑑𝑑𝑑 − 𝑓𝑓(𝑥𝑥) returning another

𝑑𝑑𝑑𝑑 𝑑𝑑𝑑𝑑 function

24
Agar Agar (Anyhow) Derivative

• We know that, given a function f, the derivative of f is


𝑑𝑑𝑑𝑑(𝑥𝑥) 𝑓𝑓 𝑥𝑥 + ∆𝑥𝑥 − 𝑓𝑓(𝑥𝑥)
= lim
𝑑𝑑𝑑𝑑 ∆𝑥𝑥→0 ∆𝑥𝑥

• But, if we have very small number dx


𝑑𝑑𝑑𝑑(𝑥𝑥) 𝑓𝑓 𝑥𝑥 + 𝑑𝑑𝑑𝑑 − 𝑓𝑓(𝑥𝑥)

𝑑𝑑𝑑𝑑 𝑑𝑑𝑑𝑑

25
Agar Agar (Anyhow) Derivative

Take in a function,
returning another
function

26
Agar Agar (Anyhow) Derivative

𝑑𝑑 sin 𝑥𝑥
Derivatives cos 𝑥𝑥
𝑑𝑑𝑑𝑑

𝑑𝑑 (𝑥𝑥 3 + 3𝑥𝑥 − 1) Derivatives 3𝑥𝑥 2 + 3


𝑑𝑑𝑑𝑑

27
Application Example
of deriv()

28
Example: Newton’s method

• To compute root of function g(x), i.e. find x such that g(x) = 0

1. Anyhow assume the answer x = something


2. If g(x) ≈ 0 then stop: answer is x, return x
3. Otherwise
• x = x – g(x)/deriv(x)
4. Go to step 2

29
Example: Newton’s method

• To compute root of function g(x), i.e. find x such that g(x) = 0

1. Anyhow assume the answer x = something


2. If g(x) ≈ 0 then stop: answer is x, return x
3. Otherwise
• x = x – g(x)/deriv(x)
4. Go to step 2

30
Example: Newton’s method

• To compute the root of function g(x), i.e. find x such that g(x) = 0

31
Example: Newton’s method

• Example: Square root of a number A


 It’s equivalent to solve the equation: 𝑥𝑥 2 − 𝐴𝐴 = 0

32
Example: Newton’s method

• Example: Compute log10 (A)


 Solve the equation: 10𝑥𝑥 − 𝐴𝐴 = 0

33
34
You can solve any
equation!
…. that Newton Method can solve.

35
Lambda functions
Lambda functions

Abstraction is right associative

(
f = lambda a, b: (lambda x: b(b(a))) )

Application is left associative

(f (‘b’, lambda a: a*3))( (lambda a: a[:1]))


Lambda functions

(
f = lambda a, b: (lambda x: b(b(a))) )
(f (‘b’, lambda a: a*3))( (lambda a: a[:1]))
lambda x: ((lambda a: a*3)(lambda a: a*3)(‘b’)))

lambda x: ((lambda a: a*3) (‘bbb’))

lambda x: ( ‘bbbbbbbbb’)
(f (‘b’, lambda a: a*3))( (lambda a: a[:1]))

(lambda x: ‘bbbbbbbbb’) (lambda a: a[:1])

‘bbbbbbbbb’

39
(Text) File Input/Output
You can
download any
data!
Open in
• Excel
• Notepad
Let’s Do it in Python
• Of course, you are not going to type the data
into your Python code
– one data one code?!
– change in data = change in code?
– Called “Hard Coding”
• Usually practice
– Data file +
– Python code that can read the file
Writing A File

Actually Easier
Writing A File
Indicate the file
object f is for writing

The file object that we


called it “f” (can be any
variable name)

Use the file “f” to write


something in it
Writing A File
Writing a File The newline
character
Different File Opening Modes
Different File Opening Modes
• Default is text
format
• Storing in text
mode is very space
consuming
• E.g. storing the
date ‘20180901’
– Text (ASCII):
• 50 48 49 56 48
57 48 49
– Binary (Integer):
• 01 33 EF A5
Reading a File
Try it out
• I have a text file called “student_marks.txt”
file name The file
object

read the whole file into


“data” as a string

The new line


character
String Operation Split
• Use the function split to separate the string
into a list of strings by a separator

• If you do not put any argument for split(), the


default separators are space and newline
Try it out Starting from the
second position and
step two

• Extract all the scores

Convert each string


into an integer
Reading One Whole File into a String
• That’ is not “healthy”
• Your file can be a few MB or even GB

• Then this line of code will run in a very long


time, may even end in crashing the whole
program or even the system
• Better way to do is to read the file line-by-line
Reading the File Line-by-line

The file type is also


“iterable”!!!
If you do it in Python Shell (bad)

The file as an
“iterable”
console echo

Annoying newline
character ‘\n’

• How should we deal with these “\n”?


A More Complicated Example
Open in
• Excel
• Notepad
Reading Data in Python
• You can start reading a file in Python by

• The line is read with a ‘\n’ (newline)


Reading Data

extra new line because


of ‘\n’
rstrip(): Strip Characters on the Right

no more extra new line


String rstrip() and split()
Let’s start writing the code

• The file object ‘f’ is an iterable


• Every iteration you have a hidden
line = f.readline()
Let’s start writing the code

A string
Let’s Split!

Split by
space!!!
Let’s Split Commas!
Let’s manage our data
• We want to plot the year against the birthday
– The value of the birth rate is x per thousand
– So the actual no. of birth is x times 1000
Convert
into integers
Discard the
first line

“line”
Discard the
first line

“line”
Discard the
first line

“line”
Now You Know Why “Baby Bonus”
Read in a Reading CSV Files Create a CSV File
CSV file Reader
into a list

Remember these
four lines of code

No need for all


those string
strip(), split() etc.
Today
• You have learned how to read and write a file
– Or more precisely, reading or writing a general file
– In fact, we got an easier way to read a CSV file
• Wait until we learn multi-dimensional arrays
• You can say that you “finished” the (most of
the) “core” Python Language
• The rest is extra packages, features
Sequences and Higher Order
Functions
Scaling a Sequence
• Given a sequence of numbers, how to scale every element?
• Let’s say, scale by 2
[5,1,4,9,11,22,12,55]

[10,2,8,18,22,44,24,110]
Scaling a Sequence
• Given a sequence of numbers, how to scale every element?
Squaring a Sequence
• Given a sequence of numbers, how to square every element?

[5,1,4,9,11,22,12,55]

[25, 1, 16, 81, 121, 484, 144, 3025]
Squaring/Scaling a Sequence
• Other than the function name (that can change to anything), what is
the difference?

• What should we do with other operations to a sequence?


• E.g. cube, abs, etc.?
• What should we do with other operations to a sequence?
• E.g. cube, abs, etc.?
Difference Operations on a Sequence
Our map()
• However, our map() can only
process list
• Cannot work on other
sequences like tuples, strings,
etc.
• However, Python does have
its original version of map()
• But it will return a type “map”
object
• You can convert that object
into other sequences like list or
tuples
Python’s map()
Python’s map()
• The map object is actually an
“iterable”
• After you ”took out” items from
the map object, the items will be
”gone”

• Conclusion
• Conversion from a map object to
a tuple or list only once
Kattis Demo
• https://open.kattis.com/problems/electricaloutlets
Python’s Filter
Python’s Filter
• Python’s map()
• Apply a function f to every item x in the sequence
• Python’s filter()
• Apply a predicate function f to every item x in the sequence
• A predicate is a function that return True or False
• Return an iterable that
• Keep the item if f(x) returns True
• Remove the item otherwise
Python’s filter()
Counting a Sequence
Shallowly or Deeply
How to Count the Number of Element in a
Sequence?

• Of course we can use len()


• But what if we want to implement it ourselves?
However, it’s Shallow

• How to count ”deeply”?

• And what about a list like this


Counting Logic? Shallow Count
• Total count = count of the first item + count of the rest
• But the count of the first item is always 1

• Can we do the same thing for deep count?


• What is the difference between deep and shallow count?
• In deep count, the “length” of the first item may not be 1
Counting Logic? Deep Count
• Total count = count of the first item + count of the rest
• But the count of the first item is only 1 if it’s not a sequence
• [1,2,3,4,[2,3,4],[1]]
• The first item has a count 1
• [[1,2],3,4,5]
• The first item does not has a count 1
• Two questions:
• How to tell the first item is a sequence or not?
• What to do if the first item is a sequence?
First Question
• How to tell the first item is a list or not a list
• Assuming we only have list
• Not difficult to extend to tuples
• Check
type(seq[0])==list
• E.g.
Second Question
• If the first item is NOT a list, e.g. [1,2,3,4,[2,3,4],[1]]
• count of the first item is 1
• If the first item IS a list, e.g. [[1,2],3,4,5]
• recursively compute deepcount() of the first item!

• And this can handle if the first item is a list of a list of a list of ….
• e.g.
• [[[[[1,2],2],4],2],3,4,5]
Second Question
• If the first item is NOT a list, e.g. [1,2,3,4,[2,3,4],[1]]
• count of the first item is 1
• If the first item IS a list, e.g. [[1,2],3,4,5]
• recursively compute deepcount() of the first item!
Simple Test
deepcount([1])

deepcount(1) + deepcount([])
Whenever we
reached this line
Count + 1
Simple Test
deepcount([1,2,3])

deepcount(1) + deepcount([2,3])

deepcount(2) + deepcount([3])

deepcount(3) + deepcount([])
x
Tracing the Code
[]

• x = [[[1,2],3],9,[1,2]]

[] 9 []

[] 3 1 2

1 2
x
Tracing the Code
[]

deepcount([[[1,2],3],9,[1,2]])

[] 9 []

[] 3 1 2
deepcount([[1,2],3])+deepcount([9,[1,2]])

1 2
x
Let’s Consider the Left Term
[]

deepcount([[1,2],3])

[] 9 []

deepcount([1,2]) + deepcount([3])
[] 3 1 2

deepcount(1) + deepcount([2]) 1 2

deepcount(2)+deepcount([]) deepcount(3)+deepcount([])
x
Let’s Consider the Left Term
[]

deepcount([[1,2],3])

[] 9 []

deepcount([1,2]) + deepcount([3])
[] 3 1 2

deepcount(1) + deepcount([2]) 1 2

deepcount(2)+deepcount([]) deepcount(3)+deepcount([])
x
Let’s Consider the Left Term
[]

deepcount([[1,2],3]]) ☞ 3

[] 9 []

[] 3 1 2

1 2
x
Tracing the Code
[]

deepcount([[[1,2],3],9,[1,2]])

[] 9 []

[] 3 1 2
deepcount([[1,2],3]])+deepcount([9,[1,2]])

1 2

3 +deepcount([9,[1,2]])
x
Tracing the Code
[]

deepcount([9,[1,2]])

[] 9 []
deepcount(9)+deepcount([[1,2]])

[] 3 1 2
deepcount([1,2]) + deepcount([])

1 2
deepcount(1) + deepcount([2])

deepcount(2) + deepcount([])
x
Tracing the Code
[]

deepcount([9,[1,2]])

[] 9 []
deepcount(9)+deepcount([[1,2]])

[] 3 1 2
deepcount([1,2]) + deepcount([])

1 2
deepcount(1) + deepcount([2])

deepcount(2) + deepcount([])
x
Tracing the Code
[]

deepcount([9,[1,2]]) ☞ 3

[] 9 []

[] 3 1 2

1 2
x
Tracing the Code
[]

deepcount([[[1,2],3],9,[1,2]])

[] 9 []

[] 3 1 2
deepcount([[1,2],3]])+deepcount([9,[1,2]])

1 2

3 + 3 = 6
x
Tracing the Code
[]

• x = [[[1,2],3],9,[1,2]]

[] 9 []

[] 3 1 2

1 2
How about ….
• DeepSquare?

• Deep Increment (by 1)?


Get Some Insight from DeepCount?
DeepSquare
• Spot the difference?
DeepSquare
• Base case is different
• If seq is reduced to an empty list, return it as it is
DeepSquare
• The leaf case
• If the item is not a list, return its square instead of 1
DeepSquare
• Otherwise
• Return the list of recursive call of the first item
• Huh? Why not return the “recursive call of the first item”? Why an extra “layer” of list?
• And concatenate with the recursive call of the “rest” of the list
deepSquare([2])

[deepSquare(2)] + deepSquare([])

[2*2] + [] ☞ [4]
DeepInc
• How different from DeepSquare?
deepMap !!!!
deepMap!!!
Remember List Copy by copy()?

• Shallow copy!!!!!!!! (Please refer to tutorials)


deepCopy()

• And it works!
Why Do I Want to Go
“Deep”?
Copying a Directory
• When the directory contains a
lot of files in many
subdirectories
Computer Animation
• Skeleton animation
Shortest Path Tree
Image Processing
• An image is a list of lists of lists
• The first level list: rows
• The second level of lists: column
• The third level of lists: RGB values
• Map a function to change
certain values
• E.g. change colors
How about if I just want to
be shallow?
How about if I just want to be shallow?
• Given a nested list, output a list with all the elements but without any
Flatten()

flatten([[[1]]])
flatten([[1]]) + flatten([])
flatten([1]) + flatten([]) + flatten([])
flatten(1) + flatten([]) + flatten([]) + flatten([])
[1] + flatten([]) + flatten([]) + flatten([])
Conclusions
• map() is a powerful tool in Python
• Allows you to perform a lot of operations with less redundant code
• Deep operations are useful to solve problems with non-linear data
• E.g. Trees, n-dim arrays, graphs
• Using recursive functions wisely is the key for algorithms
• Higher level of coding
Dimensions
• Are we living in a three dimensional space?

The xkcd guide to the fourth dimension


Two-dimensional Array
Motel in US (1D)

Rm 1 Rm 2 Rm 3 Rm 4 Rm 5

One Dimension
My room is 02-05
Hotel (2D)

4F 1 2 3 4 5 6
3F 1 2 3 4 5 6
2F 1 2 3 4 5 6
1F 1 2 3 4 5 6
Chess Position
• Row 8
• Col B
• So, B8
Dimensions
One Dimensional Array, A Two Dimensional Array, M
Index Contents
0 1 2 3
0 ‘Apple’
0 ‘Apple’ ‘Lah’ ‘Cat’ ‘Eve’
1 ‘John’
1 ‘Hello’ ‘Pay’ ‘TV’ ‘Carl’
2 ‘Eve’
2 ‘What’ ‘Bank’ ‘Radio’ ‘Ada’
3 ‘Mary’
3 ‘Frog’ ‘Peter’ ‘Sea’ ‘Eat’
4 ‘Ian’

5 ‘Smith’ 4 ‘Job’ ‘Fry’ ‘Gym’ ‘Wow’

6 ‘Kelvin’ 5 ‘Walk’ ‘Fly’ ‘Cook’ ‘Look’

A[5] = ‘Smith’ M[4][1] = ‘Fry’


2-Dimensional Array in Python
• 1-d array • 2-d array

Column index

Row index

• Equivalent to
1 2
3 4
What is the Difference Between …
• A list of lists • 2D Array
– More specifically, all the – Is a subset of a list of lists
lists do not have to be #rows,
the same length Can be any length
Length = 3 Can be any length, but
Length = 3 all the lists have to be
the same length

[[1,2],[3,4,5],[6]] [[1,2],[3,4],[5,6]]
Length = 2 Length = 3 Length = 1 Length = 2 Length = 2 Length = 2

1 2
3 4
A Larger 2-d Array
• Creating a 4 x 10 matrix

pprint() from
the package
pprint makes
the format nicer
Number of rows

Number of columns
To Create an N x N Identical Matrix

Row i

Column j
2D Looping
• Let’s say we just want to print 0 and 1
2D Looping
• Let’s say we just want to print 0 and 1
j=0123456789
↓↓↓↓↓↓↓↓↓↓

i=0→
i=1→
i=2→
i=3→
i=4→
Row i i=5→
i=6→
i=7→
i=8→
i=9→

Column j
To Create an R x C Zero Matrix
Accessing Entries
• Remember
– Frist row index
– Then column index

i=1→


j=3
2D Array Applications
• Matrix operations
• Recoding 2D data
– Tables
– Spatial Data
Matrix Addition

• How do to Matrix
Multiplication or
other matrix
operations, e.g.
inverse, transpose?
Tables
• Just like other Spreadsheet applications
Name Stu. No. English Math Science Social Studies
John A1000000A 90 80 100 70
Peter A1000009D 60 100 60 90
Paul A1000003C 80 80 70 90
Mary A1000001B 100 70 80 80
Tables
• Like in Spreadsheet applications
Name Stu. No. English Math Science Social Studies
John A1000000A 90 80 100 70
Peter A1000009D 60 100 60 90
Paul A1000003C 80 80 70 90
Mary A1000001B 100 70 80 80

• Or, you can setup a more “comprehensible”


column index dictionary
Tables
• You can even append a new record for a new
student
Tables
• Or do any computations on the table
– E.g. The average of the English scores
Spatial Data

Tic-tac-toe, Chess, SRPG


Tic-tac-toe
• Tic-tac-toe
– A game of 3 x 3 grid
– How to represent the game?
• A 3 x 3 Matrix:
game = createZeroMatrix(3,3)
• How to ”make a move”?
– You can directly ask the user to input a pair of
coordinates, e.g. (1,1)
– However, sometime it’s confusing for users who
cannot tell row indices from column indices
Tic-tac-toe
• Because the grid size is very small, we can
make it easier for the user by labeling each
box with a number from 1 to 9
• For the position pos from 1 to 9, we can map
to the coordinates (i,j) as
i = (pos-1)//3
j = (pos-1)%3

• Challenge
– Given the row and column indices i and j, how to
compute the position pos?
A Simple TTT Game
• First, for a matrix game that represent the
current state of the game, let’s make a
function to print it nicely
A Simple TTT Game
Create the game
board
A Simple TTT Game
Put the number 1 to
9 into the board for
display purposes
A Simple TTT Game
There are two players,
Player 0 and Player 1
Player 0 uses ‘X’
Player 1 uses ‘O’

The first player is Player 0

And they will take turns


A Simple TTT Game
Anyhow play 9 times
(We didn’t implement any
error or winning checking
yet)
Gameplay
Chess
Other Text Based Chess
Chess
• How to make a move?
• E.g. moving a knight
– Maybe
game[7][1] = 0
game[5][2] = ‘K’
Chinese Checkers?
• How to represent the board?
3D Chess
Other 2D Array Games
RPG, SRPG
Game of Life
• https://bitstorm.org/gameoflife/
• Virus Riddle
circlePic()
ASCII Arts
Wait…
• What if I put three colors as each of the item
in my 2D array?

[100,20
Red, green, blue
0,100] = [100,200,100]
2D and 3D Arrays
2D Arrays 3D Arrays
• A list of lists • A list of lists of lists
• A vehicle loading with • A vehicle loading with
vehicles vehicles loading with
– And each vehicle contains vehicles
some passengers – And each vehicle contains
some passengers
2+1 = 3D Array as a Picture
One pixel is a list
of three values of
red, blue and
green.
Usually ranging
from 0 to 255

imshow() is to
draw a picture in
bitmap

• 3 x 3 (x 3 for colors) pixels


(zoomed)
Recap: circlePic()
Image Processing
Using the imagio package to read in a photo as a 3D
Negative Image
Negative Image

The picture has h x w numbers of pixels


(h = #rows, w = #columns)
Loop through each pixel with indices (i,j)
Image Processing
Dyeing Hair

Loop through each pixel with indices (i,j)

If pic[i][j] has more green, change it to purple


Multi-dimensional Array
2+1 = 3D Array as a Picture
One pixel is a list
of three values of
red, blue and
green.
Usually ranging
from 0 to 255

imshow() is to
draw a picture in
bitmap

• 3 x 3 pixels (zoomed)
Dimensions
One Dimensional Array, A Two Dimensional Array, M
Index Contents
0 1 2 3
0 ‘Apple’
0 ‘Apple’ ‘Lah’ ‘Cat’ ‘Eve’
1 ‘John’
1 ‘Hello’ ‘Pay’ ‘TV’ ‘Carl’
2 ‘Eve’
2 ‘What’ ‘Bank’ ‘Radio’ ‘Ada’
3 ‘Mary’
3 ‘Frog’ ‘Peter’ ‘Sea’ ‘Eat’
4 ‘Ian’

5 ‘Smith’ 4 ‘Job’ ‘Fry’ ‘Gym’ ‘Wow’

6 ‘Kelvin’ 5 ‘Walk’ ‘Fly’ ‘Cook’ ‘Look’

A[5] = ‘Smith’ M[4][1] = ‘Fry’


Multi-Dimensional Array
• A three dimensional array
Fancy Terminology in Business
• Multidimensional Data Model
• Multidimensional Analysis
Sales Cube
• Product Type x Year x Country

• 4th Dimensional Sales Cube:


– Product Type x Year x Country x {Predicted vs
actual}
Multi-Dimensional Array
• Year x Ethnic Group x {death/birth}
And…. how can we forget?!
Voxels
• 2D element: Pixels
• 3D element: Voxels
Reading a CSV File
2D Array x CSV
• Remember last time, we plotted the Singapore
birth rate with the data in a CSV file
Read in a Reading CSV Files Create a CSV File
CSV file Reader
into a list

Remember these
four lines of code

No need for all


those string
strip(), split() etc.
Caution
• Again, using lists or tuples?
• Again, the old list referencing problem
Conclusion
• Dimensionality is not that difficult
– If you can move from 1D to 2D, moving to 3D or
ND is not that difficult
• In bosonic string theory, spacetime is 26-dimensional,
while in superstring theory it is 10-dimensional, and in
M-theory it is 11-dimensional.
• MD-arrays solve a lot of problems
– Math, images, engineering, robotics, AI,
Object-Oriented
Programming
OOP
Recap: Tables
• Just like other Spreadsheet applications
Name Stu. No. English Math Science Social Studies
John A1000000A 90 80 100 70
Peter A1000009D 60 100 60 90
Paul A1000003C 80 80 70 90
Mary A1000001B 100 70 80 80

• How about more “attributes”


Name Stu. No. Gender Year English Math Science Social Studies
John A1000000A M 2018 90 80 100 70
Peter A1000009D M 2018 60 100 60 90
Paul A1000003C M 2017 80 80 70 90
Mary A1000001B F 2019 100 70 80 80
NUS Application
Stored as a 2D Array
• Like in Spreadsheet applications
Name Stu. No. English Math Science Social Studies
John A1000000A 90 80 100 70
Peter A1000009D 60 100 60 90
Paul A1000003C 80 80 70 90
Mary A1000001B 100 70 80 80

• Or, you can setup a more “comprehensible” column index dictionary


Isn’t it nicer?
>>> alan.name
'Alan'
>>> alan.gender
'M'
>>> alan.sci
80
>>> alan.math
100
>>> mary.name
'Mary'
>>> mary.sn
'A1000002A'
>>> allStudents = [alan,mary]
>>> allStudents[0].name
'Alan'
>>> allStudents[1].sn
'A1000002A'
Class and Instance
Definitions
• Class:
• specifies the common behavior of entities.
• a blueprint that defines properties and behavior of an object.
• Instance:
• A particular object or entity of a given class.
• A concrete, usable object created from the blueprint.
Classes vs Instances
• Class • Instance
• Blueprints, designs • Actual copies you use

One blueprint can produce a lot of copies of iPhone


One class can produce a lot of copies of instances
Example
• String is a class in Python

• The variable s above, is an instance of the class str (String)


• And you can create other instances, e.g. s1, str1, s2, etc. of ONE class str
• And each instance will store different values
Designing our own class
• Python OOP means we can design our own class and methods!

• Let’s try to create a class called “StudentRecord”


Class StudentRecord
• Design
• In a student record, we want to
store
• Name, student number, gender,
year, and marks for English,
math, science and social studies
• Or maybe more?

In OOP, these are


called attributes
Class StudentRecord
• Design
• In a student record, we want to
store
• Name, student number, gender,
year, and marks for English,
math, science and social studies
• Or maybe more? ↕
• But this is ONLY the class
• Namely the blueprint
• Can we use this phone
blueprint to call someone?
• You have to MAKE a phone by it
Create an Instance
• When you create a new instance/variable:
>>> alan = StudentRecord()
• It’s like you create a new variable x for integer
>>> x = 1
• A new instance/variable is born/created
• Important:

When you create an instance, the


constructor function is called
A “self” variable?
• Every class definition has access to a self variable
• self is a reference to the entire instance
What is __init__()?
• def __init__(self):
• called when the object is first initialized
• self argument is a reference to the object calling the method.
• It allows the method to reference properties and other methods of
the class.
• Are there other special methods?
• Yes! Special methods have __ in front and behind the name
Create an Instance
• When you create a new instance/variable:
>>> alan = StudentRecord()
• When you create an instance, the constructor
function is called
• What? What constructor?!
• In every class, you have to define a function
called “__init()__”
With two underscores “_ _”
• “self” means your own record
• To distinguish from a local variable in a function (as we had
learn so far) that will be destroyed after the function ended
Create an Instance
• When you create a new instance/variable:
>>> alan = StudentRecord()
• When you create an instance, the constructor
function is called
• So after the line above, the instance alan will
contain
• So, the values in the constructor can be considered
the default vales for initialization
You Store Values into an Instance

Before the red arrow Finally. (Oops, I


forgot to assign
“year”)
Create as Many Instances
as You Want
A “self” variable?
• Every class definition has access to a self variable
• self is a reference to the entire instance
• A self variable will NOT disappear when the function exits
With or without “self.”
• The variable “name” will disappear after the
completion of the function __init__()
• The variable “self.name” will remain after
the completion of the function
__init__()
Other than Student Records
Or Bank Accounts
• What attributes should we store in a bank
account record?
• Name
• Balance
• Isn’t it a bit clumsy to set the values?
• We know that some attributes must be
initialized before used
Initialization through Constructors
• We know that some attributes must be initialized before used
• When we create an instance, we initialize through the constructor

• It is a good way to “force” the instance to be initialized


Modifying Attributes
• Of course, we can change the attributes of any instance

• However, is it always good to be changed like that?

• There are always some rules to control how to modify the attributes
• In real life, how do you withdraw money from your account?
“Rules”
• Can you walk in the bank and get any amount even more than your
balance? Or any other bank transactions?
• Must through some “mechanism”, e.g.
• Bank tellers, ATM, phone/internet banking, etc.
• And these mechanisms have some rules,
• E.g. you cannot withdraw more than your balance
Bank Accounts with “Methods”

Attributes

Methods
Bank Accounts with “Methods”
>>> myAcc = BankAccount('Alan',1000)
>>> myAcc.showBalance()
Your balance is $1000
>>> myAcc.withdraw(123)
123
>>> myAcc.showBalance()
Your balance is $877
>>> myAcc.withdraw(99999)
Money not enough! You do not have $99999
0
Is it a *really* a new thing?
• Recall your previous lectures…
lst = [1, 2, 3]
lst.append(4)
lst [1, 2, 3, 4]

• Conceptually, append is a method defined in the List class.


• Just like withdraw is a method defined in the BankAccount
class
Inheritance
Let’s Define a class Sportcar
Test Run
>>> myCar = Sportscar((0,0))
>>> myCar.setVelocity(0,40)
>>> myCar.move()
Move to (0, 40)
>>> myCar.turnOnTurbo()
VROOOOOOOM......
Velocity increased to (0, 80)
>>> myCar.move()
Move to (0, 120)
How about a class Lorry?
How about a class Lorry?
Test Run
>>> myTruck = Lorry((10,10)) >>>myTruck.unload("Food")
>>> myTruck.setVelocity(10,0) Cargo Food unloaded.
>>> myTruck.move() >>> myTruck.inventory()
Move to (20, 10) Inventory:['Supplies']
>>> myTruck.load("Food") >>> myTruck.unload("Gold")
>>> myTruck.load("Supplies") Cargo Gold not found.
>>> myTruck.inventory()
Inventory:['Food', 'Supplies']
Compare the Two Classes
Sportscar Lorry
• Attributes • Attributes
• pos • pos
• velocity • velocity
• cargo
• Methods • Methods
• __init__() • __init__()
• setVelocity() • setVelocity()
• move() • move()
• turnOnTurbo() • load()
• unload()
• inventory()

What are the common attributes/methods?


Compare the Two Classes
Sportscar Lorry
• Attributes • Attributes
• pos • pos
• velocity • velocity
• cargo
• Methods • Methods
• __init__() • __init__()
• setVelocity() • setVelocity()
• move() • move()
• turnOnTurbo() • load()
• unload()
• inventory()

What are the common attributes/methods?


Extract the Vehicle
• Attributes
Common • pos
Pattern! • velocity
• Methods
• __init__()
• setVelocity()
• move()

Sportscar Lorry
• Methods • Attributes
• __init__() • cargo
• turnOnTurbo() • Methods
• __init__()
• load()
• unload()
• inventory()
The Classes Vehicle and Sportcar

Sportscar inherits EVERYTHING from Vehicle


How about Lorry?
• In the OLD Lorry code

Extra to the __init__()


in Vehicle
If We Inherit Lorry from Vehicle
• Two ways to implement the
constructor
• Method 1: Overriding
• Simple redefining the method will
override the one in Vehicle
or
• Method 2: Calling super class
• Redefine a constructor, but call the
constructor in super() (Vehicle
class) instead
Super()
• A way to access a method in your parent/higher classes
Which one is better?
• Usually we prefer Method 2
because
• No duplication of code

• Method 2: Calling super class


• Redefine a constructor, but call the
constructor in super() (Vehicle
class) instead
Class Lorry
• Inherit all what class
Vehicle has
• In addition, add
more functionalities
like load() and
unload()
Vehicle
• Attributes
Overall Picture • pos
Super class
or
Parent class
• velocity
• Methods
• __init__()
• setVelocity()
Subclass • move()
or
Child class

Sportscar Lorry
• Methods • Attributes
• __init__() • cargo
• turnOnTurbo() • Methods
• __init__()
• load()
• unload()
• inventory()
Inheritance
• Objects that exhibit similar functionality should “inherit” from the
same base object, called the superclass.
• An object that inherits from another is called the subclass.
Subclass and
Superclass
• Usually a subclass is a more
specific type of its parent
class
• Like our classification of
animals, any “children” in
the tree is a more “specific”
type of the “parents”
• (Unless we talk about
multiple inheritance later)
Let’s define a new class Bisarca
• Car carrier trailer
• It is a type of truck that carries other cars
• The truck and also load and unload, but only for cars
• not any type of cargos
Where should
we put class Vehicle
Bisarca? • Attributes: pos,velocity
• Methods:__init__(),setVelocity(),move()

Sportscar Lorry
• Methods: __init__(), • Attributes: cargo
turnOnTurbo() • Methods:__init__(),load(),unload()
,inventory()

Bisarca
• Methods: load()
Class Bisarca

• The function isinstance(obj,cal) check if an instance obj is


a class or subclass of a certain class cal.
Sample Run
>>> myDadTruck = Bisarca((0,0))
>>> myDadTruck.load("Food")
Your cargo (Food) is not a vehicle!
>>> myDadTruck.load(myCar)
>>> myDadTruck.load(myTruck)
>>> myDadTruck.inventory()
Inventory:[<__main__.Sportcar object at 0x10d3ecd50>,
<__main__.Lorry object at 0x10d39dc10>]
Method Overriding
• When you redefine a same method that was in your parent class
• You own class will call your new redefined method
• Instead of your parent’s one
• This is called overriding Lorry
• Attributes: cargo
• Methods:__init__(),load(),unload
(),inventory()

Bisarca
• Methods: load()
Multiple Inheritance
Let’s Create a Class Cannon
Class Cannon
• Sample run:
>>> myCannon = Cannon()
>>> myCannon.fire()
No more ammo
>>> myCannon.reload()
Cannon reloaded
>>> myCannon.reload()
Unable to reload
>>> myCannon.fire()
Fire!!!!!!!
>>> myCannon.fire()
No more ammo
What Do You Have When You…
• Merge a cannon and a vehicle?

+ =
We Want to Have BOTH!
>>> myTank = Tank((0,0))
>>> myTank.setVelocity(40,10)
>>> myTank.move()
Move to (40, 10)
>>> myTank.move()
Move to (80, 20)
>>> myTank.reload()
Cannon reloaded
>>> myTank.fire()
Fire!!!!!!!
Where should we put the class Tank?
Vehicle Cannon
• Attributes: pos,velocity • Attributes: numAmmo
• Methods: setVelocity(),move() • Methods: fire()

Sportscar Lorry Tank


• Methods: __init__(), • Attributes: cargo
turnOnTurbo() • Methods:__init__(),load(),
unload(),inventory()

Bisarca
• Methods: load()
A Bit Trouble
• Which constructor __init__() should the Tank call?

• Seems like we need BOTH

Call BOTH!!!
Resolving Methods
So far we have
Vehicle Cannon
• Attributes: pos,velocity • Attributes: numAmmo
• Methods: setVelocity(),move() • Methods: fire()

Sportscar Lorry Tank


• Methods: __init__(), • Attributes: cargo
turnOnTurbo() • Methods:__init__(),load(),
unload(),inventory()

Bisarca
• Methods: load()
What Do You Have When You…
• Merge a Bisarca and a Cannon?

+ =
Let’s Construct Class BattleBisarca

• Wait… Which load() is called?


Vehicle Cannon
• Attributes: pos,velocity • Attributes: numAmmo
• Methods: setVelocity(),move() • Methods: fire()

Lorry
• Attributes: cargo Which
• Methods:__init__(),load() load() is
,unload(),inventory()
called by
Bisarca BattleBisarca
• Methods: load() ?
BattleBisarca
Vehicle Cannon
• Attributes: pos,velocity • Attributes: numAmmo
• Methods: setVelocity(),move() • Methods: fire()

Lorry
• Attributes: cargo The nearest
• Methods:__init__(),load() one will be
,unload(),inventory()
called
Bisarca
• Methods: load()

BattleBisarca
Let’s Constuct Class BattleBisarca

• Wait… Which load() is called?


>>> OptimasPrime = BattleBisarca((0,0))
>>> OptimasPrime.load("Food")
Your cargo (Food) is not a vehicle!
Class A
Multiple Inheritance
• Complication arises when the same
method is available in two distinct Class B Class C
superclasses
• And how about Diamond Inheritance
• But if you are really interested in these Class D
• Check out:
• http://python-
history.blogspot.com/2010/06/method-
resolution-order.html
Multiple Inheritance
• Not many OOP Language support MI
• E.g. no MI in C++, Java
• MI causes more trouble sometime because you may call the
unexpected method in a complicated inheritance structure
• Recommendation is, only use MI if the parents are very different
• E.g. Vehicle and Cannon
• Or Tablet (computer) + calling device = smart phone
Private vs Public
Private vs Public
• So far, all our methods in a class are all public
• Meaning they can be called with the instance
• E.g. for the class BankAccount
• Even we set up the method withdraw() to “prevent” illegal access

• But we can still do


>>> myAcc.showBalance()
Your balance is $1000
>>> myAcc.balance -= 9999
>>> myAcc.showBalance()
Your balance is -$8999
Another Example: Remember the Bisarca?
>>> myDadTruck.load(myCar) So ugly
>>> myDadTruck.load(myTruck)
>>> myDadTruck.inventory()
Inventory:[<__main__.Sportcar object at
0x10d3ecd50>, <__main__.Lorry object at
0x10d39dc10>]
• What I really want is
>>> myDadTruck.inventory()
Inventory:['Sportscar', 'Lorry']
So I change my Bisarca class into

• Wait, but I actually do not want anyone to use the method


convertCargo(), it’s not for anyone
• I want to make it private
Private Methods
• If you add two underscore before the method name
class Bisarca(Lorry):
def __convertCargo(self):
output = []
for c in self.cargo:
output.append(str(type(c)).split('.')[1].split('\'')[0])
return output
def inventory(self):
print("Inventory:"+str(self.__convertCargo()))
• That function can be used inside your class but cannot be called outside!
>>> myDadTruck.__convertCargo()
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
myDadTruck.__convertCargo()
AttributeError: 'Bisarca' object has no attribute '__convertCargo'
Private but not Private
• However, it’s not very true…
• You can add ‘_’ and the class name to access it
>>> myDadTruck._Bisarca__convertCargo()
['Sportscar', 'Lorry']
• But why do we have this?!
“Private” Methods
• Originally, in a lot of other OOP languages (e.g. C++, Java), a private
method/variable will NOT be accessible by anyone other than the
class itself.
• The purpose is to prevent any programmers to access the
method/variable in a wrong way
• E.g. directly change the balance of a bank account like
myAcc.balance = 100000000
• However, Python does not have that “full protection”
Don’t forget Archipelagos
Conclusion
Benefits of OOP
• Pros
• Simplification of complex, possibly hierarchical structures
• Easy reuse of code
• Easy code modifiability
• Intuitive methods
• Hiding of details through message passing and polymorphism
• Cons
• Overhead associated with the creation of classes, methods and instances
Major Programming Paradigms
• Imperative Programming
• C, Pascal, Algol, Basic, Fortran
• Functional Programming
• Scheme, ML, Haskell,
• Logic Programming
• Prolog, CLP
• Object-oriented programming
• Java, C++, Smalltalk

Python??
Image Processing
Installing Python Packages
• Python comes with built-in functions
• However, you need to manually install
additional packages
– In Assignment 0, the instructions asked you to
install, imageio, numpy, etc
• In this lecture we will need “imageio”
– To install “imageio” (or any other packages), go to
cmd.exe
• Type “pip install imageio”
• Provided you have your internet connected
• pip will download the package and install it
for you
We have all these photo apps

https://www.everydayfamily.com/slideshow/10-hilariously-awful-photoshop-fails/
Image Processing
• To load an image, you can use the package
“imageio”
Image Processing
• 600 x 600 pixel
– And each pixel has
three values of R, G
and B
– [R, G, B]
Image Processing
Col 0 Col 1 Col 2 …… Col 599
• 600 x 600 pixel Row 0 (R,G,B) (R,G,B) (R,G,B) (R,G,B)
– [R, G, B] Row 1 (R,G,B)
Row 2 (R,G,B)
– 0 <= R,G,B <=255
.
.
.
.
.
.

Row 599 (R,G,B) (R,G,B)


Image Processing
• Remember sub-matrix, string slicing, etc.?
Broadcasting

• every pixel
multiply by
– [R,G,B] x [0,1,0] =
– [R x 0, G x 1, B x 0]
– [0, G, 0 ]
Array Broadcasting

“Broadcasting”

Different from LIST

Create another array with the Boolean results


Negative Image
2D Array looping
How to….?
Making a Mask
dim[0]//3

dim[0]

(xcenter,ycenter)

dim[1]
Making a Mask
If the pixel is out
of the circle

Each color of the


pixel is divided by 2
Your
picture
array

• Any time you want to save an image:


imageio.imsave('file name.png', cat_pic)
Rotating an Image
Applying Filters

Blending on x
NO Blending on
colors

Blending on y
Applying Filters
• sigma = (3,3,1) • sigma = (9,9,1)
Edge Detection
• Anyhow generate an image
More in Numpy and Scipy
• Fourier Transform
• Uniform filter
• Histogram
• Laplace… etc

• More on
– https://docs.scipy.org/doc/scipy/reference/ndimage.h
tml
PILLOW

A Fork in PIL
PILLOW is a fork of PIL
• PIL stands for Python Imaging Library
Let’s get the secret out
PILLOW
• Cannot escape!
PILLOW
Original

Blurred Sharpen
Copy And Paste Copy (crop)
the part of
the picture

Paste it on
the position
(0,400)
Other operations
• resize
• rotation/flipping
• traspose
• Drawing shapes
• etc. etc..

https://pillow.readthedocs.io/en/stable/
Other Than Scipy and Numpy
• OpenCV
• skimage
– scikit-image
Searching
Searching
• You have a list.
• How do you find something in the list?

• Basic idea: go through the list from start to


finish one element at a time.
Linear Search
• Idea: go through the list from start to finish

5 2 3 4

• Example: Search for 3


5 2 3 4
3 not found, move on
5 2 3 4

3 not found, move on


5 2 3 4

Found 3.
Linear Search
Idea: go through the list from start to finish

# equivalent code
for i in [5, 2, 3, 4]:
if i == 3:
return True
Linear Search
Implemented as a function:
def linear_search(value, lst):
for i in lst:
if i == value:
return True
return False

What kind of performance can we expect?


Large vs small lists?
Sorted vs unsorted lists?
Can we do better?
Searching
IDEA:
If the elements in the list were sorted in order, life
would be much easier.

Why?
IDEA
If list is sorted, we can
“divide-and-conquer”

Assuming a list is sorted in ascending order:


𝑎 𝑥
0 1 … 𝑘 … 𝑛−2 𝑛−1
𝑎 𝑥
0 1 … 𝑘 … 𝑛−2 𝑛−1

if the th element is larger than what we are


looking for, then we only need to search in the
indices
Binary Search
1. Find the middle element.
2. If it is what we are looking for (key), return True.
3. If our key is smaller than the middle element, repeat
search on the left of the list.
4. Else, repeat search on the right of the list.
Binary Search
Looking for 25 (key)
5 9 12 18 25 34 85 100 123 345

Find the middle element: 34


5 9 12 18 25 34 85 100 123 345

Not the thing we’re looking for: 34 25


5 9 12 18 25 34 85 100 123 345

25 34, so we repeat our search on the left half:


5 9 12 18 25 34 85 100 123 345
Binary Search
Find the middle element: 12

5 9 12 18 25 34 85 100 123 345

25 12, so we repeat the search on the right half:

5 9 12 18 25 34 85 100 123 345

Find the middle element: 25

5 9 12 18 25 34 85 100 123 345

Great success: 25 is what we want

5 9 12 18 25 34 85 100 123 345


Binary Search
“Divide and Conquer”
In large sorted lists, performs much better
than linear search on average.
Binary Search
Algorithm (assume sorted list):
1. Find the middle element.
2. If it is we are looking for (key), return True.
3. A) If our key is smaller than the middle element, repeat
search on the left of the element.
B) Else, repeat search on the right of the element.
Binary Search
def binary_search(key, seq):
if seq == []:
return False
mid = len(seq) // 2
if key == seq[mid]:
return True
elif key < seq[mid]:
return binary_search(key, seq[:mid])
else:
return binary_search(key, seq[mid+1:])
Binary Search
def binary_search(key, seq): # seq is sorted
def helper(low, high):
if low > high:
return False
mid = (low + high) // 2 # get middle
if key == seq[mid]:
return True
elif key < seq[mid]:
return helper(low, mid-1)
else:
return helper(mid+1, high)
return helper(0, len(seq)-1)
Binary Search
Now let’s try searching for 11:
5 9 12 18 25 34 85 100 123 345

def binary_search(key, seq):


def helper(low, high): Step 1. Find the
if low > high:
return False middle element.
mid = (low + high) // 2
if key == seq[mid]:
return True
elif key < seq[mid]:
return helper(low, mid-1)
else:
return helper(mid+1, high)
return helper(0, len(seq)-1)
Binary Search
Now let’s try searching for 11:
5 9 12 18 25 34 85 100 123 345

def binary_search(key, seq): key  11


def helper(low, high):
if low > high:
return False
mid = (low + high) // 2
if key == seq[mid]:
return True
elif key < seq[mid]:
return helper(low, mid-1)
else:
return helper(mid+1, high)
return helper(0, len(seq)-1) helper(0, 10-1)
Binary Search
Now let’s try searching for 11:
5 9 12 18 25 34 85 100 123 345

def binary_search(key, seq):


def helper(low, high): # 0, 9 Step 1. Find the
if low > high:
return False middle element.
mid = (low + high) // 2 # mid=4
if key == seq[mid]:
return True
elif key < seq[mid]:
return helper(low, mid-1)
else:
return helper(mid+1, high)
return helper(0, len(seq)-1)
Binary Search
Now let’s try searching for 11:
5 9 12 18 25 34 85 100 123 345

def binary_search(key, seq):


def helper(low, high): # 0, 9 Step 2. If it is
if low > high:
return False what we are
mid = (low + high) // 2 # mid=4
if key == seq[mid]: # 11 == 25 looking for,
return True
elif key < seq[mid]: return True
return helper(low, mid-1)
else:
return helper(mid+1, high)
return helper(0, len(seq)-1)
Binary Search
Now let’s try searching for 11:
5 9 12 18 25 34 85 100 123 345

def binary_search(key, seq):


def helper(low, high): # 0, 9 Step 3a. If key is
if low > high:
return False smaller, look at
mid = (low + high) // 2 # mid=4
if key == seq[mid]: # 11 == 25 left side
return True
elif key < seq[mid]: # 11 < 25
return helper(low, mid-1) # helper(0, 4-1)
else:
return helper(mid+1, high)
return helper(0, len(seq)-1)
Binary Search
Now let’s try searching for 11:
5 9 12 18 25 34 85 100 123 345

def binary_search(key, seq):


def helper(low, high): # 0, 3 Step 3a. If key is
if low > high:
return False smaller, look at
mid = (low + high) // 2 # mid=4
if key == seq[mid]: # 11 == 25 left side
return True
elif key < seq[mid]:
return helper(low, mid-1)
else:
return helper(mid+1, high)
return helper(0, len(seq)-1)
Binary Search
Now let’s try searching for 11:
5 9 12 18 25 34 85 100 123 345

def binary_search(key, seq):


def helper(low, high): # 0, 3 Step 1. Find the
if low > high:
return False middle element
mid = (low + high) // 2 # mid=1
if key == seq[mid]:
return True
elif key < seq[mid]:
return helper(low, mid-1)
else:
return helper(mid+1, high)
return helper(0, len(seq)-1)
Binary Search
Now let’s try searching for 11:
5 9 12 18 25 34 85 100 123 345

def binary_search(key, seq):


def helper(low, high): # 0, 3 Step 2. If it is
if low > high:
return False what we are
mid = (low + high) // 2 # mid=1
if key == seq[mid]: # 11 == 9 looking for,
return True
elif key < seq[mid]: return True
return helper(low, mid-1)
else:
return helper(mid+1, high)
return helper(0, len(seq)-1)
Binary Search
Now let’s try searching for 11:
5 9 12 18 25 34 85 100 123 345

def binary_search(key, seq):


def helper(low, high): # 0, 3 Step 3a. If key
if low > high:
return False is smaller, look
mid = (low + high) // 2 # mid=1
if key == seq[mid]: # 11 == 9 at left side
return True
elif key < seq[mid]: # 11 < 9
return helper(low, mid-1)
else:
return helper(mid+1, high)
return helper(0, len(seq)-1)
Binary Search
Now let’s try searching for 11:
5 9 12 18 25 34 85 100 123 345

def binary_search(key, seq):


def helper(low, high): # 0, 3 Step 3b. Else
if low > high:
return False look at right
mid = (low + high) // 2 # mid=1
if key == seq[mid]: # 11 == 9 side
return True
elif key < seq[mid]: # 11 < 9
return helper(low, mid-1)
else:
return helper(mid+1, high) # helper(1+1, 3)
return helper(0, len(seq)-1)
Binary Search
Now let’s try searching for 11:
5 9 12 18 25 34 85 100 123 345

def binary_search(key, seq):


def helper(low, high): # 2, 3 Step 3b. Else
if low > high:
return False look at right
mid = (low + high) // 2
if key == seq[mid]: side
return True
elif key < seq[mid]:
return helper(low, mid-1)
else:
return helper(mid+1, high)
return helper(0, len(seq)-1)
Binary Search
Now let’s try searching for 11:
5 9 12 18 25 34 85 100 123 345

def binary_search(key, seq):


def helper(low, high): # 2, 3 Step 3b. Else
if low > high:
return False look at right
mid = (low + high) // 2
if key == seq[mid]: side
return True
elif key < seq[mid]:
return helper(low, mid-1)
else:
return helper(mid+1, high)
return helper(0, len(seq)-1)
Binary Search
Now let’s try searching for 11:
5 9 12 18 25 34 85 100 123 345

def binary_search(key, seq):


def helper(low, high): # 2, 3 Step 1. Find
if low > high:
return False the middle
mid = (low + high) // 2 # mid=2
if key == seq[mid]: element
return True
elif key < seq[mid]:
return helper(low, mid-1)
else:
return helper(mid+1, high)
return helper(0, len(seq)-1)
Binary Search
Now let’s try searching for 11:
5 9 12 18 25 34 85 100 123 345

def binary_search(key, seq):


def helper(low, high): # 2, 3 Step 2. If it is
if low > high:
return False what we are
mid = (low + high) // 2 # mid=2
if key == seq[mid]: # 11 == 12 looking for,
return True
elif key < seq[mid]: return True
return helper(low, mid-1)
else:
return helper(mid+1, high)
return helper(0, len(seq)-1)
Binary Search
Now let’s try searching for 11:
5 9 12 18 25 34 85 100 123 345

def binary_search(key, seq):


def helper(low, high): # 2, 3 Step 3a. If key
if low > high:
return False is smaller, look
mid = (low + high) // 2 # mid=2
if key == seq[mid]: # 11 == 12 at left side
return True
elif key < seq[mid]: # 11 < 12
return helper(low, mid-1) # helper(2, 2-1)
else:
return helper(mid+1, high)
return helper(0, len(seq)-1)
Binary Search
Now let’s try searching for 11:
5 9 12 18 25 34 85 100 123 345

def binary_search(key, seq):


def helper(low, high): # 2, 1 Step 3a. If key
if low > high:
return False is smaller, look
mid = (low + high) // 2
if key == seq[mid]: at left side
return True
elif key < seq[mid]:
return helper(low, mid-1)
else:
return helper(mid+1, high)
return helper(0, len(seq)-1)
Binary Search
Now let’s try searching for 11:
5 9 12 18 25 34 85 100 123 345

def binary_search(key, seq):


def helper(low, high): # 2, 1 Key cannot be
if low > high: # 2 > 1
return False found. Return
mid = (low + high) // 2
if key == seq[mid]: False
return True
elif key < seq[mid]:
return helper(low, mid-1)
else:
return helper(mid+1, high)
return helper(0, len(seq)-1)
Binary Search
• Each step eliminates the problem size by half.
- The problem size gets reduced to 1 very quickly
• This is a simple yet powerful strategy, of halving the solution
space in each step
• What is the order of growth?
Wishful Thinking
We assumed the list was sorted.

Now, let's deal with this assumption!


Sorting
Sorting
• High-level idea:
1. some objects
2. function that can order two objects
 order all the objects
How Many Ways to
Sort?
Too many. 
Example
Let’s sort some playing cards?
What do you do when
you play cards?
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.

Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.

Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.

Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.

Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.

Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.

Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.

Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.

Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.

Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.
Repeat
Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.
Repeat
Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.
Repeat
Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.
Repeat
Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.
Repeat
Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.
Repeat
Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.
Repeat
Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.
Repeat
Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.
Repeat
Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.
Repeat
Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.
Repeat
Unsorted

Sorted Smallest
Obvious Way
Find the smallest card not in hand (SCNIH), and put it at the
end of your hand. Repeat.
Done
Unsorted

Sorted Smallest
There is actually a name for this:
Selection Sort!
Let’s Implement it!
a = [4,12,3,1,11]
sort = []

while a: # a is not []
smallest = a[0]
for element in a:
if element < smallest:
smallest = element
a.remove(smallest)
sort.append(smallest)
print(a)
Output
[4, 12, 3, 11]
[4, 12, 11]
[12, 11]
[12]
[]
print(a)
[]

print(sort)
[1, 3, 4, 11, 12]
Order of Growth?
• Time: Worst
Average
Best

• Space:
Let’s try something
else…
suppose you have a
friend
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Split into halves
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Split into halves
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.

How to combine the 2 sorted halves?


Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Compare first elements
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Compare first elements
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Compare first elements
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Compare first elements
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Compare first elements
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Compare first elements
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Compare first elements
Doing it with a friend
• Split cards into two halves and sort. Combine halves
afterwards. Repeat with each half.
Compare first elements
There is also a name for this:
Merge Sort!
Let’s Implement It!
First observation: RECURSION!
• Base case: n< 2, return lst
• Otherwise:
- Divide list into two
- Sort each of them
- Merge!
Merge Sort
def merge_sort(lst):
if len(lst) < 2: # Base case!
return lst
mid = len(lst) // 2
left = merge_sort(lst[:mid]) #sort left
right = merge_sort(lst[mid:]) #sort right
return merge(left, right)

How to merge?
How to merge?
• Compare first element
• Take the smaller of the two
• Repeat until no more elements
Merging
def merge(left, right):
results = []
while left and right:
if left[0] < right[0]:
results.append(left.pop(0))
else:
results.append(right.pop(0))
results.extend(left)
results.extend(right)
return results
Order of Growth?
• Time: Worst
Average
Best

• Space:
No need to memorize
Sort Properties
In-place: uses a small, constant amount of
extra storage space, i.e., space

Selection Sort: No (Possible)


Merge Sort: No (Possible)
Sort Properties
Stability: maintains the relative order of
items with equal keys (i.e., values)

Selection Sort: Yes (maybe)


Merge Sort: Yes
How Many Ways to
Sort?
Too many. 
Summary
• Python Lists are mutable data structures
• Searching
- Linear Search
- Binary Search: Divide-and-conquer
• Sorting
- Selection Sort
- Merge Sort: Divide-and-conquer + recursion
- Properties: In-place & Stability
Ok, now I know how to guess a number
quickly
Google?
How much data does Google handle?
• About 10 to 15 Exabyte of data
- 1 Exabyte(EB)= 1024 Petabyte(PB)
- 1 Petabyte(PB) = 1024 Terabytes(TB)
- 1 Terabyte(PB) = 1024 Gigabytes(TB)
•= 4 X 256GB iPhone
• So Google is handling about 60 millions of
iPhones
How fast is my desktop?
Return the time in
seconds since the
epoch (1970/1/1
00:00) as a floating
point number.

Create 100M of
numbers, estimated
to be 400MB of data
Output:
Let’s calculate
• 400M of data needs 6 seconds
• 15 Exabyte of data needs how long?
- 15 EB = 15 x 1024 x 1024 x 1024 x 1024 MB
- To search through 15EB of data…..
•7845 years…..

• If we do it with Binary Search


- log2 (15EB) = 43 steps!!!!!
The Power of Algorithm
Order of Growth
In Physics, We consider
• Time

• Space
In CS, we consider
• Time
• how long it takes to run a
program

• Space
• how much memory do we
need to run the program
Order of Growth Analogy
• Suppose you want to buy a Blu-
ray movie from Amazon
(~40GB)
• Two options:
• Download
• 2-day Prime Shipping

• Which is faster?
The Infinity Saga Box Set
Order of Growth Analogy
• Buy the full set?
• 23 movies

• Two options:
• Download
• 2-day Prime Shipping

• Which is faster?
Order of Growth Analogy
• Or even more movies?
Download vs Delivery
Time
Download

2 days Delivery

1 hour
# of movies
Ultimate Question
• If the ”volume” increased
• How much more resources, namely time and space,
grow?
Will they grow in the same manner?
• From • From
• factorial(10) • fib(10)
• To • To
• factorial(20) • fib(20)
• To • To
• factorial(100) • fib(100)
• To • To
• factorial(10000) • fib(10000)
Order of Growth

•is NOT…
•The absolute time or space a program
takes to run
•is
•the proportion of growth of the
time/space of a program w.r.t. the growth
of the input
Let’s try it on something we know
def factorial(n):

if n <= 1:
return 1
else:
return n * factorial(n – 1)

def fib(n):

if (n == 0):
return 0
elif (n == 1):
return 1
else:
return fib(n – 1) + fib(n – 2)
Let’s try it on something we know
nfact, nfib = 0,0
def factorial(n):
global nfact
nfact +=1
if n <= 1:
return 1
else:
return n * factorial(n – 1)

def fib(n):
global nfib
nfib +=1
if (n == 0):
return 0
elif (n == 1):
return 1
else:
return fib(n – 1) + fib(n – 2)
Compare
>>> factorial(5) >>> fib(5)
120 5
>>> nfact >>> nfib
5 15
>>> nfact = 0 >>> nfib = 0
>>> factorial(10) >>> fib(10)
3628800 55
>>> nfact >>> nfib
10 177
>>> nfact = 0 >>> nfib = 0
>>> factorial(20) >>> fib(20)
2432902008176640000 6765
>>> nfact >>> nfib
20 21891
Order of Growth of Factorial
>>> factorial(5)
factorial(5)
120
• Factorial is simple
>>> nfact • If the input is n, then the function factorial(4)
5 is called n times
>>> nfact = 0
>>> factorial(10)
• Because each time n reduced by 1
factorial(3)
3628800 • So the number of times of
>>> nfact
10
calling the function is factorial(2)
>>> nfact = 0 proportional to n
>>> factorial(20) factorial(1)
2432902008176640000
>>> nfact
20
Fib
• More complicated >>> fib(5)
5
>>> nfib1
5
>>> nfib = 0
>>> fib(10)
55
>>> nfib
177
>>> nfib = 0
>>> fib(20)
Why?
6765
>>> nfib
21891
Fibonacci: Tree recursion root
fib(5)

fib(4) fib(3)

fib(3) fib(2) fib(2) fib(1)

fib(1) fib(1) fib(0) fib(1) fib(0) 1


fib(2)

1 1 0 1 0
fib(1) fib(0)

1 0 • Roughly half of a full tree


• And a full tree has 2n-1 nodes
leaves
Compare
>>> factorial(5) >>> fib(5)
120 5
>>> nfact >>> nfib1
5 5
>>> nfact = 0 >>> nfib = 0
>>> factorial(10) >>> fib(10)
3628800 55
>>> nfact >>> nfib
10 177
>>> nfact = 0 >>> nfib = 0
>>> factorial(20) >>> fib(20)
2432902008176640000 6765
>>> nfact >>> nfib
20 21891

No of calls proportional to n No of calls proportional to 2n


Searching in a list of n items
• Linear search • Binary search
• # comparisons proportional to n • # comparisons proportional to log n
• (Because in average, the expected • Because, we divide the list into half
number of search is n/2) for at most log n times
Bubble Sort
8 4 5 9 2 3 7 1 6 0
4 8 5 9 2 3 7 1 6 0
4 5 8 9 2 3 7 1 6 0
4 5 8 9 2 3 7 1 6 0
4 5 8 2 9 3 7 1 6 0
4 5 8 2 3 9 7 1 6 0
4 5 8 2 3 7 9 1 6 0
4 5 8 2 3 7 1 9 6 0
4 5 8 2 3 7 1 6 9 0
4 5 8 2 3 7 1 6 0 9
Bubble Sort
4 5 8 2 3 7 1 6 0 9
4 5 8 2 3 7 1 6 0 9
4 5 8 2 3 7 1 6 0 9
4 5 2 8 3 7 1 6 0 9
4 5 2 3 8 7 1 6 0 9
4 5 2 3 7 8 1 6 0 9
4 5 2 3 7 1 8 6 0 9
4 5 2 3 7 1 6 8 0 9
4 5 2 3 7 1 6 0 8 9
Bubble Sort
Sorting a list of n Items
• Selection/Bubble Sort • Merge sort
• # comparisons proportional to n2 • # comparisons proportional to n log n
• Because we looped n times, and • Because, we divide the list into half for at
each time you need to arrange 1 most log n times
to n items • And each time arrange n items
Comparison
Algorithm
Anyone can give some algorithms
BogoSort
• BogoSort(L)
• Repeat:
• Choose a random permutation of the list L.
• If L is sorted, return L.
• If you wait enough time, L is sorted?
Bogo Sort

• Randomly shuffle the list till the list is sorted

Can we do better?
Hill-Climbing for Sorting
• Optimization algorithm
• Require an evaluation function

• Which metric is better for evaluation?


• Let 𝑚𝑚𝑚𝑚_𝑙𝑙𝑙𝑙𝑙𝑙𝑙𝑙 be our list
• Number of index pairs 𝑖𝑖, 𝑗𝑗 such that such that 𝑚𝑚𝑚𝑚_𝑙𝑙𝑙𝑙𝑙𝑙𝑙𝑙[𝑖𝑖] > 𝑚𝑚𝑚𝑚_𝑙𝑙𝑙𝑙𝑙𝑙𝑙𝑙[𝑗𝑗]

• Example: 𝑉𝑉𝑉𝑉𝑉𝑉𝑉𝑉𝑉𝑉(𝑚𝑚𝑚𝑚_𝑙𝑙𝑙𝑙𝑙𝑙𝑙𝑙) = 4 + 1 + 2 + 1 = 8

𝑉𝑉𝑉𝑉𝑉𝑉𝑉𝑉𝑉𝑉(𝑚𝑚𝑚𝑚_𝑙𝑙𝑙𝑙𝑙𝑙𝑙𝑙) = 0 + 0 + 0 + 0 = 0
Hill-Climbing for Sorting

• Repeat the following either till value of the list is zero or a


predetermined number of times
• Shuffle the list
• Accept the shuffled list if its value is lower than that of current list
Algorithm
Anyone can give some algorithm

But how fast is your algorithm?


How about
QuantumBogoSort(A[1..n])
a) Choose a random permutation of the array A.
b) If A is sorted, return A.
c) If A is not sorted, destroy the universe.

• Remember QuantumBogoSort when you learn about non-


deterministic Turing Machines
Improvement?
Let’s try fib(n)
Easy Way: Memoization Instead of recomputing
fib(3) here
fib(5)

fib(4) fib(3)

fib(3) fib(2) fib(2) fib(1)

fib(1) fib(1) fib(0) fib(1) fib(0) 1


fib(2)

1 1 0 1 0
fib(1) fib(0)

1 0
We save the result when
it was computed
Memoization
• Create a dictionary to
remember the answer
if fibm(n) is
computed before
• If the ans was
computed before, get
the answer from the
dictionary
• Otherwise, compute
the ans and put it into
the dictionary for later
use
Can you use Memoization to
compute nCk?
Recursion Removal

• Store all the answers in


an array
• Add a new fib(i)
• as fib(i-1) + fib(i-2)

• Wait a min…
• Do we need all the past
numbers if we only need
fib(n)?
Recursion Removal 2
• Add a new fib(i)
• as fib(i-1) + fib(i-2)
• And I only need to keep fib(i-1) and fib(i-2)
Improvement
• For IT5001, you should know how to compute fib(n) with time
proportional to n
• The fastest algorithm to compute fib(n) with time proportional to log n
• To know more about this to improve human race and save the world
• CS1231, CS2040, CS3230, etc
• What you learn today is called the Big O notation
• O(n), O(log n), O(n2), O(n log n), O(2n), etc
Errors And Exception
Types of Errors

• Until now error messages haven’t been more than mentioned, but
you have probably seen some
• Two kinds of errors (in Python):
1. Syntax errors
2. Exceptions
Syntax Errors
>>> while True print('Hello world')
SyntaxError: invalid syntax
Exceptions
• Errors detected during execution are called exceptions
• Examples:
Type of Exception Description
NameError If an identifier is used before assignment
TypeError If wrong type of parameter is sent to a function
ValueError If function parameter has invalid value (Eg: log(-1))
ZeroDivisionError If 0 is used as divisor
StopIteration Raised by next(iter)
IndexError If index is out of bound for a sequence
KeyError If non-existent key is requested for set or dictionary
IOError If I/O operation fails (eg: opening a file)
EOFError If end of file is reached for console of file input
AttributeError If an undefined attribute of an object is used
NameError
>>> 4 + spam*3
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
4 + spam*3
NameError: name 'spam' is not defined
TypeError
>>> '2' + 2
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
'2' + 2
TypeError: Can't convert 'int' object to str
implicitly
ValueError
>>> int('one')
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
int('one')
ValueError: invalid literal for int() with base
10: 'one'
ZeroDivisionError
>>> 10 * (1/0)
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
10 * (1/0)
ZeroDivisionError: division by zero
Other Common Errors
StopIteration Error
IndexError

KeyError
Handling Exceptions (Errors)

10
Handling Exceptions

• Two Approaches

• Using Guard Clauses

• Using Try-Except-Else constructs

11
12
Guard Clauses

Guard is a Boolean expression that


must evaluate to True if the program
execution is to continue in the
branch in question

13
Raising Exceptions

14
Raising Exceptions

• The raise statement allows the programmer to force a specific


exception to occur:

>>> raise NameError('HiThere')


Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: HiThere
Raising Exceptions

raise terminates the function and shows the message

16
Raising Exceptions checking for multiple types

17
Guard Clauses: Use with Caution
• Python can raise exceptions without explicit guard clauses
• Checking for a specific exception may consume resources (eg: time)
• Especially if it is done within a loop with several iterations

18
Handling Exceptions

19
Handling Exceptions
• The simplest way to catch and handle exceptions is with a try-except
block:

x, y = 5, 0
try:
z = x/y
except ZeroDivisionError:
print("divide by zero")
How it works

• The try clause is executed


• If an exception occurred, skip the rest of the try
clause, to a matching except clause
• If no exception occurs, the except clause is skipped
(go to the else clause, if it exists)
• The finally clause is always executed before
leaving the try statement, whether an exception has
occurred or not.
Try-Except
• A try clause may have more than 1 except clause,
to specify handlers for different exception.
• At most one handler will be executed.
• Similar to if-elif-else
• finally will always be executed
Try-Except
try:
try: except Error1:
# statements
except Error1: #handle error 1
# handle error 1
except Error2: except Error2:
# handle error 2
except: # wildcard else: #handle error 2
# handle generic error
else: except:
# no error raised finally:
#handle
finally:
generic error
# always executed
Try-Except Example
def divide_test(x, y):
try:
result = x / y
except ZeroDivisionError:
print("division by zero!")
else:
print("result is", result)
finally:
print("executing finally clause")
Try-Except Blocks def divide_test(x, y):
>>> divide_test(2, 1) try:
result is 2.0 result = x / y
executing finally clause except ZeroDivisionError:
print("division by zero!")
else:
>>> divide_test(2, 0)
print("result is", result)
division by zero! finally:
executing finally clause print("executing finally
clause")
>>> divide_test("2", "1")
executing finally clause
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'
Simulation of for loop using while Loop
Example: How to use exceptions

• Remember our tic-tac-toe?


• We would like the user to input the
number from 1 to 9
• We assume that the user is good to enter it
obediently
• But not the real life situation in life
• There is always mistake or naughty users
How to make sure your user input is a
number?
• Original code:
pos = int(input(f'Player {piece[player]} move:')) - 1
• You can do a lot of checking, e.g.
userinput = input(f'Player {piece[player]} move:')
if userinput.isnumeric():
#play as normal
else:
#error and input again
• However, it requires:
• You can consider ALL wrong situations
• And you can check them all out with codes
Example:

• If the user input an integer


• Nothing wrong
• break, exit the while loop
• Otherwise, go to “except:”
• Hence, will not break the while loop
Try-Except: Checking for Single Exception
If exceptions occur rarely, Try-Except is better than guard clauses

We can check multiple exceptions

30
Try-Except: Multiple Exceptions
Check each exception and
provide specific message

31
Try-Except: Multiple Exceptions
Check for multiple exceptions
simultaneously

32
Checking for all exceptions

33
Try-Except-Finally

This block is always executed

34
Exception Types
• Built-in Exceptions:
https://docs.python.org/3/library/exceptions.html
• User-defined Exceptions
User-defined Exceptions I
class MyError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
User-defined Exceptions II
try:
raise MyError(2*2)
except MyError as e:
print('Exception value:', e.value)
Exception value: 4

raise MyError('oops!')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
__main__.MyError: 'oops!'
Assertion
• For example, in tic-tac-toe, you also assume the position is from 1 to 9
• For a lot of situations, you ”assume” certain conditions in your code, e.g.
• A sorting function will only take sequences as input
• A function checking prime number will only take in integers
• In a certain part of your code, you expect some index 𝑖𝑖 will not exceed a certain
range
• In Python, you can simply add an assertion
• If the statement following in the assertion is False, then EXCEPTIONS!
• Raises an AsserionError
Example

• Assert that the pos must be within range


Example

• In order to catch the particular exception of the assertion, we can


Why use Exceptions?

•In the good old days of C, many procedures


returned special ints for special conditions,
i.e. -1
Why use Exceptions?
• But Exceptions are better because:
• More natural
• More easily extensible
• Nested Exceptions for flexibility
Data Visualization with Python

“A picture is worth a thousand words”


Why Visualization?!

VS
Why Visualization?
• Meet the need for speed
• For yourself, a tool to understand your data
• For your audience
– Addressing data quality
– Displaying meaningful results
– Dealing with outliers
• For yourself, for your supervisors, for your
boss!
Numpy
• A convenient package • For example, if you
• You can get around with want to create a list of
“normal” Python numbers from 0 to π
method but Numpy can without Numpy you
shorten your code a lot have to:
Numpy
Be Careful!!!
This is not “arrange”
but “arange”
Another Way Be Careful!!!
This is not
“linespace” but
“linspace”

.
.
.
Using matplotlib
You can Simply
Plotting cos(x)
• Without Numpy, you have to

• With Numpy, you simply do


But the x-range
is wrong!
• If you only specify one list (or any sequence),
each item will be plotted against just an
integer
More Curves (Lab 00)

Green color
and label

Not very nice


looking when the
curve is touching
the boundary

Position
of the
legend
Title
Set the
vertical limits
to be -1.5 to
1.5
Changing Markers/Line Style
Try it out
-- dashed
: dotted
-. dash dotted
- solid
o circle
< triangle_left
+ plus

Details of ALL markers:


https://matplotlib.org/api/markers_api.html
Multiple Figures

Only affect
the most
recent graph
Multiple Figures

How many rows r are


there

How many columns c


are there

After dividing the figure into r


x c places, which one do you
want to place the current
plotting
4 rows Position 1
3 columns

Position 9
If you really have a lot of figures
The following plotting will be in Figure 1

The following plotting will be in Figure 2


Bar Chart
Bar Chart
Histogram
• Similar to bar chart, but a histogram groups
numbers into ranges
• E.g. Given data: heights of 30 trees from
150cm to 350cm
Number of
Trees

• Usually bar charts have gaps


– But histograms have no gap
Let’s Roll
• When you roll three dices and
sum the number, which
number has the highest
chance?
• Application
– E.g. in Monopoly, if you start
from “GO!”, which place(s)
has/have the highest probability
to be landed on?
Rolling 3 dices
3=1+1+1
4=1+1+2
5=1+1+3=2+2+1
6=1+1+4=1+2+3=2+2+2
7=1+1+5=2+2+3=3+3+1=1+2+4
8=1+1+6=2+3+3=4+3+1=1+2+5=2+2+4
9=6+2+1=4+3+2=3+3+3=2+2+5=1+3+5=1+4+4
10 = 6 + 3 + 1 = 6 + 2 + 2 = 5 + 3 + 2 = 4 + 4 + 2 = 4 + 3 + 3 = 1 + 4 + 5
11 = 6 + 4 + 1 = 1 + 5 + 5 = 5 + 4 + 2 = 3 + 3 + 5 = 4 + 3 + 4 = 6 + 3 + 2
12 = 6 + 5 + 1 = 4 + 3 + 5 = 4 + 4 + 4 = 5 + 2 + 5 = 6 + 4 + 2 = 6 + 3 + 3
13 = 6 + 6 + 1 = 5 + 4 + 4 = 3 + 4 + 6 = 6 + 5 + 2 = 5 + 5 + 3
14 = 6 + 6 + 2 = 5 + 5 + 4 = 4 + 4 + 6 = 6 + 5 + 3
15 = 6 + 6 + 3 = 6 + 5 + 4 = 5 + 5 + 5
16 = 6 + 6 + 4 = 5 + 5 + 6
17 = 6 + 6 + 5
18 = 6 + 6 + 6
Study Monopoly
• Rolling three dices, what is the range?
– 3 to 18
– Totally 16 different combinations
• All combinations have the same probability?
– NO!
• Then what are the probabilities?
– We can do calculations
– But I forgot all my math already!?!?!?
Rolling 3 dices
Probability of a sum of 3: 1/216 = 0.5%
Probability of a sum of 4: 3/216 = 1.4%
Probability of a sum of 5: 6/216 = 2.8%
Probability of a sum of 6: 10/216 = 4.6%
Probability of a sum of 7: 15/216 = 7.0%
Probability of a sum of 8: 21/216 = 9.7%
Probability of a sum of 9: 25/216 = 11.6%
Probability of a sum of 10: 27/216 = 12.5%
Probability of a sum of 11: 27/216 = 12.5%
Probability of a sum of 12: 25/216 = 11.6%
Probability of a sum of 13: 21/216 = 9.7%
Probability of a sum of 14: 15/216 = 7.0%
Probability of a sum of 15: 10/216 = 4.6%
Probability of a sum of 16: 6/216 = 2.8%
Probability of a sum of 17: 3/216 = 1.4%
Probability of a sum of 18: 1/216 = 0.5%
Let’s run an experiment
why not
roll_dice()*3?

• dics_stat will contains 100000 numbers of


the sum of the dices
• Let’s say, how many “18” are there in these
100000 numbers?
Histogram Number
of bins
Number
of times
of >= 10
and < 11

Number
of times
of >= 3
and < 4
Histogram
• Usually, histograms won’t have a bin for every
single number x
– 3 <= x < 4
• For example, if the data is the salary, every bin
will have a larger range
– 1000 <= x < 2000
– 2000 <= x < 3000
– etc.
Histogram
• Back to the dice example, say we want the
ranges:
– 3 <= x < 7
– 7< = x < 11
– 11<= x < 15
– 15 <= x < 19
• Then we need 4 bins
Application: Monopoly
• Is every place has a equal chance to be landed
on?
– NO!
Pie Chart

Otherwise, becomes “oval” chart


Saving a Graph
• If you feel like your graph is cool and want to
save it by
– fig.savefig('plot.png'), or
– fig.savefig('plot.pdf'), or
– Any format that is supported by
matplotlib
Supported Graphic Format
• You can check the supported file format by
plt.gcf().canvas.get_supported_filetypes()

{'ps': 'Postscript', 'eps': 'Encapsulated


Postscript', 'pdf': 'Portable Document
Format', 'pgf': 'PGF code for LaTeX', 'png':
'Portable Network Graphics', 'raw': 'Raw RGBA
bitmap', 'rgba': 'Raw RGBA bitmap', 'svg':
'Scalable Vector Graphics', 'svgz': 'Scalable
Vector Graphics', 'jpg': 'Joint Photographic
Experts Group', 'jpeg': 'Joint Photographic
Experts Group', 'tif': 'Tagged Image File
Format', 'tiff': 'Tagged Image File Format'}
Other Visualization Packages
• Seaborn
Other Visualization Packages
• geoplotlib
Some Tips on GOOD Visualization
• Take a step back and ask yourself, “What is my
point?”
Now You Know Why “Baby Bonus”
Some Tips on GOOD Visualization
• Take a step back and ask yourself, “What is my
point?”
• Choose the right chart
• Use color intentionally
• The graph is bright and eye catching, yet the
color is not used in a meaningful way.
• Separating the various sites with different
colors is not important and only detracts from
the overall point.
• Using color to make the key point stand out. In
the following graph
• Use a lighter shade of red for the late planting
date, and a darker shade of red for the early
planting date.
Some Tips on GOOD Visualization
• Take a step back and ask yourself, “What is my
point?”
• Choose the right chart
• Use color intentionally
• Create pointed titles and call out key points
with text
• Get feedback and iterate
• Read up and copy other visualizations
More Help on Matplotlib
• https://matplotlib.org/users/pyplot_tutorial.h
tml

• How to FAQ
– https://matplotlib.org/faq/howto_faq.html
IT5001 Software Development
Fundamentals

16. Miscellaneous

1
Agenda

• Decorators for Memoization

• Graph Problems
 Route Problems
 Shortest Distance

2
Decorators

• Decorator is a closure
 Additionally, outer function accepts a function as input argument

• Modify input function’s behaviour with an inner function without explicitly


changing input function’s code

• Example

3
Decorators - Example

4
Decorators: Example

• Decorating functions that has arguments

5
Decorators: Example

• Decorating functions that has arguments

6
Decorators: Applications

• Profiling
 For timing functions

• Logging
 For debugging

• Caching
 For Memoization

7
Decorators for Caching

8
Fibonacci using decorators

9
Graphs
Path Between Vertices

10
Breadth-First Search

Objective:
B Checking if a path exists from
C
vertex A to vertex G

E
F

11
Graph Representation
A
• Consists of two components
 Vertices
o A,B,C,D, E, …. B
 Edges C
o (A,B), (A,C), (B,D)….
D
• How to represent it? E
 Edge List F
o Contains list of all edges
 Adjacency List/Dictionary G
o List of vertices that are adjacent to a given vertex
o Can use dictionary
• Provides mapping between each vertex and its neighbors

• Assume we are given list of edges, i.e., edge list

12
Edge List to Adjacency List

13
Breadth-First Search

14
Breadth-First Search

A
A

C B

E
F

G current ≠ destination
current 𝑛𝑛𝑛𝑛𝑛𝑛 𝑖𝑖𝑖𝑖 visited

visited = {}
frontier = [‘A’]

15
Breadth-First Search

A
A

B C D
C B

E
F

G current ≠ destination
current 𝑛𝑛𝑛𝑛𝑛𝑛 𝑖𝑖𝑖𝑖 visited

visited = {‘A’}
frontier = [‘B’, ‘C’, ’D’]

16
Breadth-First Search

A
A

B C D
C B

E
D

E
F

G current ≠ destination
current 𝑛𝑛𝑛𝑛𝑛𝑛 𝑖𝑖𝑖𝑖 visited

visited = {‘A’, ‘B’}


frontier = [‘C’, ’D’, ‘E’]

17
Breadth-First Search

A
A

B C D
C B

E F
D

E
F

G current ≠ destination
current 𝑛𝑛𝑛𝑛𝑛𝑛 𝑖𝑖𝑖𝑖 visited

visited = {‘A’, ‘B’, ‘C’}


frontier = [’D’, ‘E’, ‘F’]

18
Breadth-First Search

A
A

B C D
C B

E F G
D

E
F current 𝑛𝑛𝑛𝑛𝑛𝑛 𝑖𝑖𝑖𝑖 visited

G current ≠ destination

visited = {‘A’, ‘B’, ‘C’, ’D’}


frontier = [‘E’, ‘F’, ’G’]

19
Breadth-First Search

A
A

B C D
C B

E F G
D

E
F

G current ≠ destination
current 𝑛𝑛𝑛𝑛𝑛𝑛 𝑖𝑖𝑖𝑖 visited

visited = {‘A’, ‘B’, ‘C’, ’D’, ‘E’}


frontier = [ ‘F’, ’G’]

20
Breadth-First Search

A
A

B C D
C B

E F G
D

E
F

G current ≠ destination
current 𝑛𝑛𝑛𝑛𝑛𝑛 𝑖𝑖𝑖𝑖 visited

visited = {‘A’, ‘B’, ‘C’, ’D’, ‘E’}


frontier = [’G’]

21
Breadth-First Search

A
A

B C D
C B

E F G
D

E
F

G
current == destination
Returns 𝑇𝑇𝑇𝑇𝑇𝑇𝑇𝑇
visited = {‘A’, ‘B’, ‘C’, ’D’, ‘E’}
frontier = [ ]

22
Depth-First Search

23
Depth-First Search

A
A

C B

E
F

G current ≠ destination
current 𝑛𝑛𝑛𝑛𝑛𝑛 𝑖𝑖𝑖𝑖 visited

visited = {}
frontier = [‘A’]

24
Depth-First Search

A
A

B C D
C B

E
F

G current ≠ destination
current 𝑛𝑛𝑛𝑛𝑛𝑛 𝑖𝑖𝑖𝑖 visited

visited = {‘A’}
frontier = [‘B’, ‘C’, ’D’]

25
Depth-First Search

A
A

B C D
C B

D
G
E
F

G current ≠ destination
current 𝑛𝑛𝑛𝑛𝑛𝑛 𝑖𝑖𝑖𝑖 visited

visited = {‘A’,’D’}
frontier = [‘B’, ‘C’, ’G’]

26
Depth-First Search

A
A

B C D
C B

D
G
E
F

G current == destination

Returns 𝑇𝑇𝑇𝑇𝑇𝑇𝑇𝑇
visited = {‘A’,’D’}
frontier = [‘B’, ‘C’, ’G’]

27
Weighted Graphs

• Objective:
 Finding distance of shortest path between a source vertex and goal vertex

A
1
5
3 B
C
9 6
2 D
4
8 E
F
1 4
G

Directed Acyclic Graph


28
How to represent the Weighted graph?

• Nested Adjacency Dictionary

A
1
5
3 B
C
9 6
2 D
4
8 E
F
1 4
G

29
Algorithms

• Exhaustive Search

• Dynamic Programming, etc.

• Dijkstra’s Algorithm

30
Exhaustive Search

A
1 3
A 5
1 Search all possible routes
5 from A to G
B C D
3 B 8
C 9 6 4
2
9 6
2 D D E F F G
4 4 11
8 8 4 1 1
E
F
F G G G G
1 4
G 1 18 11 8
8

G
15

31
Recursive Algorithm
A
• Assumption 1
 Shortest distance from neighbours of 𝐴𝐴 to 𝐺𝐺 is known 5
3 B
C
• Shortest distance from 𝐴𝐴 to 𝐺𝐺 is 9 6
 min{𝑑𝑑 (𝐴𝐴, 𝑣𝑣) + 𝑑𝑑 𝑣𝑣, 𝐺𝐺 }, 𝑣𝑣 ∈ {𝐵𝐵, 𝐶𝐶, 𝐷𝐷} 2 D
4
8 E
Distance from 𝐴𝐴 Distance from
F
to its neighbour 𝑣𝑣 neighbour 𝑣𝑣 to 𝐺𝐺 4
1
G

• But how do you find distance from neighbour 𝑣𝑣 to G?


 Repeat the above process, look at its neighbours and select
shortest distance to 𝐺𝐺
 Till 𝐺𝐺 is found

32
Shortest Distance between Two Nodes

neighbours of vertex

𝑑𝑑 𝐴𝐴, 𝑣𝑣 recursive function call 𝑑𝑑 𝑣𝑣, 𝐺𝐺


obtained from problem

33
Shortest Distance: Recursive Method
𝑑𝑑(𝐴𝐴, 𝐺𝐺)
A
1 3
5

B C D
𝑑𝑑(𝐵𝐵, 𝐺𝐺) 𝑑𝑑(𝐶𝐶, 𝐺𝐺) 𝑑𝑑(𝐷𝐷, 𝐺𝐺)

𝑑𝑑 𝐴𝐴, 𝐺𝐺 = min{1 + 𝑑𝑑 𝐵𝐵, 𝐺𝐺 , 5 + 𝑑𝑑 𝐶𝐶, 𝐺𝐺 , 3 + 𝑑𝑑(𝐷𝐷, 𝐺𝐺)} 34


Shortest Distance: Recursive Method

A
1
3
5
𝑑𝑑(𝐵𝐵, 𝐺𝐺)
B D
C 𝑑𝑑(𝐶𝐶, 𝐺𝐺) 𝑑𝑑(𝐷𝐷, 𝐺𝐺)
9 6

𝑑𝑑(𝐷𝐷, 𝐺𝐺) D E 𝑑𝑑(𝐸𝐸, 𝐺𝐺)

𝑑𝑑 𝐴𝐴, 𝐺𝐺 = min{1 + 𝑑𝑑 𝐵𝐵, 𝐺𝐺 , 5 + 𝑑𝑑 𝐶𝐶, 𝐺𝐺 , 3 + 𝑑𝑑(𝐷𝐷, 𝐺𝐺)}


𝑑𝑑 𝐵𝐵, 𝐺𝐺 = min{9 + 𝑑𝑑 𝐷𝐷, 𝐺𝐺 , 6 + 𝑑𝑑 𝐸𝐸, 𝐺𝐺 }

35
Shortest Distance: Recursive Method

A
1
3
5
𝑑𝑑(𝐵𝐵, 𝐺𝐺)
B D
C 𝑑𝑑(𝐶𝐶, 𝐺𝐺) 𝑑𝑑(𝐷𝐷, 𝐺𝐺)
9 6
𝑑𝑑(𝐷𝐷, 𝐺𝐺) D E
𝑑𝑑(𝐸𝐸, 𝐺𝐺)
4 8
𝑑𝑑(𝐹𝐹, 𝐺𝐺)
F G
𝑑𝑑(𝐺𝐺, 𝐺𝐺)

𝑑𝑑 𝐴𝐴, 𝐺𝐺 = min{1 + 𝑑𝑑 𝐵𝐵, 𝐺𝐺 , 5 + 𝑑𝑑 𝐶𝐶, 𝐺𝐺 , 3 + 𝑑𝑑(𝐷𝐷, 𝐺𝐺)}


𝑑𝑑 𝐵𝐵, 𝐺𝐺 = min{9 + 𝑑𝑑 𝐷𝐷, 𝐺𝐺 , 6 + 𝑑𝑑 𝐸𝐸, 𝐺𝐺 }
𝑑𝑑 𝐷𝐷, 𝐺𝐺 = min{4 + 𝑑𝑑 𝐹𝐹, 𝐺𝐺 , 8 + 𝑑𝑑 𝐺𝐺, 𝐺𝐺 }
36
Shortest Distance: Recursive Method

A
1
3
5
𝑑𝑑(𝐵𝐵, 𝐺𝐺)
B D
C 𝑑𝑑(𝐶𝐶, 𝐺𝐺) 𝑑𝑑(𝐷𝐷, 𝐺𝐺)
9 6
𝑑𝑑(𝐷𝐷, 𝐺𝐺) D E
𝑑𝑑(𝐸𝐸, 𝐺𝐺)
4 8
𝑑𝑑(𝐹𝐹, 𝐺𝐺)
F G

1 𝑑𝑑(𝐺𝐺, 𝐺𝐺)
𝑑𝑑 𝐴𝐴, 𝐺𝐺 = min{1 + 𝑑𝑑 𝐵𝐵, 𝐺𝐺 , 5 + 𝑑𝑑 𝐶𝐶, 𝐺𝐺 , 3 + 𝑑𝑑(𝐷𝐷, 𝐺𝐺)}
G 𝑑𝑑 𝐵𝐵, 𝐺𝐺 = min{9 + 𝑑𝑑 𝐷𝐷, 𝐺𝐺 , 6 + 𝑑𝑑 𝐸𝐸, 𝐺𝐺 }
𝑑𝑑(𝐺𝐺, 𝐺𝐺)
𝑑𝑑 𝐷𝐷, 𝐺𝐺 = min{4 + 𝑑𝑑 𝐹𝐹, 𝐺𝐺 , 8 + 𝑑𝑑 𝐺𝐺, 𝐺𝐺 }
𝑑𝑑 𝐹𝐹, 𝐺𝐺 = 1 + 𝑑𝑑 𝐺𝐺, 𝐺𝐺 37
Shortest Distance: Recursive Method

A
1 3
5
𝑑𝑑(𝐵𝐵, 𝐺𝐺)
B D
C 𝑑𝑑(𝐶𝐶, 𝐺𝐺) 𝑑𝑑(𝐷𝐷, 𝐺𝐺)
9 6
𝑑𝑑(𝐷𝐷, 𝐺𝐺) D E 𝑑𝑑(𝐸𝐸, 𝐺𝐺)

4 8 4
𝑑𝑑(𝐹𝐹, 𝐺𝐺)
F G G
11
1 𝑑𝑑(𝐺𝐺, 𝐺𝐺)

G 𝑑𝑑 𝐴𝐴, 𝐺𝐺 = min{1 + 𝑑𝑑 𝐵𝐵, 𝐺𝐺 , 5 + 𝑑𝑑 𝐶𝐶, 𝐺𝐺 , 3 + 𝑑𝑑(𝐷𝐷, 𝐺𝐺)}


𝑑𝑑(𝐺𝐺, 𝐺𝐺) 𝑑𝑑 𝐵𝐵, 𝐺𝐺 = min{9 + 𝑑𝑑 𝐷𝐷, 𝐺𝐺 , 6 + 𝑑𝑑 𝐸𝐸, 𝐺𝐺 }
𝑑𝑑 𝐸𝐸, 𝐺𝐺 = 4 + 𝑑𝑑 𝐺𝐺, 𝐺𝐺
38
Shortest Distance: Recursive Method

A
1 3
5
𝑑𝑑(𝐵𝐵, 𝐺𝐺)
B D
C 𝑑𝑑(𝐶𝐶, 𝐺𝐺) 𝑑𝑑(𝐷𝐷, 𝐺𝐺)
9 6
2
𝑑𝑑(𝐷𝐷, 𝐺𝐺) D E 𝑑𝑑(𝐸𝐸, 𝐺𝐺)
F
4 8 4
𝑑𝑑(𝐹𝐹, 𝐺𝐺)
F G G
11
1 𝑑𝑑(𝐺𝐺, 𝐺𝐺)

G
𝑑𝑑(𝐺𝐺, 𝐺𝐺)
𝑑𝑑 𝐴𝐴, 𝐺𝐺 = min{1 + 𝑑𝑑 𝐵𝐵, 𝐺𝐺 , 5 + 𝑑𝑑 𝐶𝐶, 𝐺𝐺 , 3 + 𝑑𝑑(𝐷𝐷, 𝐺𝐺)}
𝑑𝑑 𝐶𝐶, 𝐺𝐺 = 2 + 𝑑𝑑(𝐹𝐹, 𝐺𝐺)
39
Shortest Distance: Recursive Method

A
1 3
5
𝑑𝑑(𝐵𝐵, 𝐺𝐺)
B D
C 𝑑𝑑(𝐶𝐶, 𝐺𝐺) 𝑑𝑑(𝐷𝐷, 𝐺𝐺)
9 6
2
𝑑𝑑(𝐷𝐷, 𝐺𝐺) D E 𝑑𝑑(𝐸𝐸, 𝐺𝐺)
F
4 8 4
𝑑𝑑(𝐹𝐹, 𝐺𝐺) 1
F G G
G
11
1 𝑑𝑑(𝐺𝐺, 𝐺𝐺)

G
𝑑𝑑(𝐺𝐺, 𝐺𝐺) 𝑑𝑑 𝐴𝐴, 𝐺𝐺 = min{1 + 𝑑𝑑 𝐵𝐵, 𝐺𝐺 , 5 + 𝑑𝑑 𝐶𝐶, 𝐺𝐺 , 3 + 𝑑𝑑(𝐷𝐷, 𝐺𝐺)}
𝑑𝑑 𝐶𝐶, 𝐺𝐺 = 2 + 𝑑𝑑(𝐹𝐹, 𝐺𝐺)
𝑑𝑑 𝐹𝐹, 𝐺𝐺 = 1 + 𝑑𝑑(𝐺𝐺, 𝐺𝐺) 40
Shortest Distance: Recursive Method

A
1 3
5
𝑑𝑑(𝐵𝐵, 𝐺𝐺)
B
C 𝑑𝑑(𝐶𝐶, 𝐺𝐺) 𝑑𝑑(𝐷𝐷, 𝐺𝐺) D
9 6
2 8
𝑑𝑑(𝐹𝐹, 𝐺𝐺) 4
𝑑𝑑(𝐷𝐷, 𝐺𝐺) D E 𝑑𝑑(𝐸𝐸, 𝐺𝐺)
F F G
𝑑𝑑(𝐹𝐹, 𝐺𝐺) 4 8 4
1
1 𝑑𝑑(𝐺𝐺, 𝐺𝐺)
F G G
G G
11
1 𝑑𝑑(𝐺𝐺, 𝐺𝐺)
𝑑𝑑(𝐺𝐺, 𝐺𝐺)

G
𝑑𝑑 𝐴𝐴, 𝐺𝐺 = min{1 + 𝑑𝑑 𝐵𝐵, 𝐺𝐺 , 5 + 𝑑𝑑 𝐶𝐶, 𝐺𝐺 , 3 + 𝑑𝑑(𝐷𝐷, 𝐺𝐺)}
𝑑𝑑(𝐺𝐺, 𝐺𝐺)

41
Shortest Distance: Recursive Method

A
1 3
5
𝑑𝑑(𝐵𝐵, 𝐺𝐺)
B
C 𝑑𝑑(𝐶𝐶, 𝐺𝐺) 𝑑𝑑(𝐷𝐷, 𝐺𝐺) D
9 6
2 8
𝑑𝑑(𝐹𝐹, 𝐺𝐺) 4
𝑑𝑑(𝐷𝐷, 𝐺𝐺) D E 𝑑𝑑(𝐸𝐸, 𝐺𝐺)
F F G
𝑑𝑑(𝐹𝐹, 𝐺𝐺) 4 8 4
1
1 𝑑𝑑(𝐺𝐺, 𝐺𝐺)
F G G
G G
11
1 𝑑𝑑(𝐺𝐺, 𝐺𝐺)
𝑑𝑑(𝐺𝐺, 𝐺𝐺)
G

𝑑𝑑(𝐺𝐺, 𝐺𝐺)

42
Shortest Distance: Memoized Recursive Version

43
Summary

• Dynamic Programming
 General Problem Solving
o Divide-and-conquer with redundant or overlapping subproblems

 Optimization
o Solving problems that have overlapping subproblems with optimal solutions
o Subproblem dependency should be acyclic (i.e., only for DAGs)

 Python’s decorators simplifies memoization in DP

44
Program Design

Modularity and reusability


Complexity

In Engineering and Programming


Project Sizes in University
• Course assignment

• Course project/FYP
Project Size at Work
Managing Complexity
Abstraction
• A technique to manage complexity
• Establishing a level of complexity on which a
person interacts with the system
• Suppressing the more complex details below
the current level.
How they work together?

?
Establish Level of Complexity
• The chief engineer want
to know
– How much fuel does the
propulsion engine uses
– How much force can the
engine provide
The level of complexity that the

• But NOT chief engineer wants to know

– How exactly the engine


works
– How many parts are
there in the engine
The level of complexity
suppressed from the chief
?

?
Compare:
def hypotenuse(a, b):
return sqrt(sum_of_squares(a, b))

def sum_of_squares(x, y):


return square(x) + square(y)

def square(x): ?
return x * x a

Versus: b
def hypotenuse(a, b):
return sqrt((a*a) + (b*b))
What Makes a Good
Abstraction?
1. Makes it more natural to think
about tasks and subtasks

Building Bricks

Floor/
story

Rooms

Bricks
1. Makes it more natural to think
about tasks and subtasks

Solution Primitives

Program

Functions

Primitives
def hypotenuse(a, b):
return sqrt(sum_of_squares(a, b))

def sum_of_squares(x, y):


return square(x) + square(y)

def square(x):
return x * x

?
a

b
1. Makes it more natural to think
about tasks and subtasks

hypotenuse operators

sum_of_squares

square

operators
2. Makes programs easier to
understand
def hypotenuse(a, b):
return sqrt(sum_of_squares(a, b))

def sum_of_squares(x, y):


return square(x) + square(y)

def square(x):
return x * x
3. Captures common patterns
• E.g. computing binomial coefficient
𝑛𝑛 𝑛𝑛!
=
𝑘𝑘 𝑘𝑘! 𝑛𝑛 − 𝑘𝑘 !

• You won’t write code like


Common
def bc(n,k): Patterns
a = code for computing 1x2x3…x n
b = code for computing 1x2x3…x k
c = code for computing 1x2x3…x(n-k)
return a / (b * c)
3. Captures common patterns
• E.g. computing binomial coefficient
𝑛𝑛 𝑛𝑛!
=
𝑘𝑘 𝑘𝑘! 𝑛𝑛 − 𝑘𝑘 !

• Write a function factorial(n) then


def bc(n,k):
a = factorial(n)
b = factorial(k)
c = factorial(n-k)
return a / (b * c)
4. Allows for code reuse
• Function square() used in sum_of_squares().
• square() can also be used in calculating area of
circle.

pi = 3.14159
def circle_area_from_radius(r):
return pi * square(r)

def circle_area_from_diameter(d):
return circle_area_from_radius(d/2)
5. Hides irrelevant details
• The structure of a gear box maybe interesting
to some fans but not everyone who drives
Made of?
How does it
work?
6. Separates specification from
implementation
• Specification: WHAT IT DOES
– E.g the function cos(x) compute the cosine of x

• Implementation: HOW IT DOES



(−1)𝑛𝑛 𝑥𝑥 2𝑛𝑛
cos 𝑥𝑥 = �
2𝑛𝑛 !
𝑛𝑛=0
Different ways of implementing
square(x)
def square(x):
return x * x

def square(x):
return x ** 2

def square(x):
return exp(double(log(x)))
def double(x): return x + x
7. Makes debugging (fixing errors)
easier
def hypotenuse(a, b):
return sqrt((a + a) * (b + b))
Where is/are
the bugs?

def hypotenuse(a,b):
return sqrt(sum_of_squares(a,b))

def sum_of_squares(x, y):


return square(x) * square(y)

def square(x):
return x + x
Good Abstraction?
1. Makes it more natural to think about tasks
and subtasks
2. Makes programs easier to understand
3. Captures common patterns
4. Allows for code reuse
5. Hides irrelevant details
6. Separates specification from implementation
7. Makes debugging easier
Program Design
Top-down Approach
pretend you have whatever you need
Sequence of Writing
1 def hypotenuse(a, b):
return sqrt(sum_of_squares(a, b))

2 def sum_of_squares(x, y):


return square(x) + square(y)

def square(x):
3
return x * x ?
a
pretend you have
whatever you need b
Another Example
• NTUC Comfort, the largest taxi operator in
Singapore, determines the taxi fare based on
distance traveled as follows:
Problem: Write a Python function
that computes the taxi fare from the
distance traveled.
How do we start?
Formulate the Problem
• We need a name!
– Pick a meaningful one
– Definitely not “foo”

Function
Formulate the Problem
• What are the
– Input?
– Output?

Distance Function Fare


Formulate the Problem
• How exactly should we design the function?
1. Try a few simple examples.
2. Strategize step by step.
3. Write it down and refine.
Solution
• What to call the function? taxi_fare

• What data are required? distance

• Where to get data? function argument

• What is the result? fare


Try a few simple examples
• e.g.#1: distance = 800 m, fare = $3.00
• e.g.#2: distance = 3300 m,
– fare = $3.00 +roundup(2300/400) × $0.22 = $4.32
• e.g.#3: distance = 14500 m,
– fare = $3.00 +roundup(9000/400) × $0.22 +
roundup(4500/350)× $0.22 = $10.92
Pseudocode
• Case 1: distance <= 1000
– fare = $3.00

• Case 2: 1000 < distance <= 10,000


– fare = $3.00 + $0.22 * roundup( (distance – 1000)/ 400)

• Case 3: distance > 10,000


– fare = $3.00 +roundup(9000/400) + $0.22 * roundup(
(distance – 10,000)/ 350)

• Note: the Python function ceil rounds up its argument.


math.ceil(1.5) = 2
Pseudocode (Refined)
• Case 1: distance <= 1000
– fare = $3.00

• Case 2: 1000 < distance <= 10,000


– fare = $3.00 + $0.22 * roundup( (distance – 1000)/ 400)

• Case 3: distance > 10,000


– fare = $8.06 + $0.22 * roundup( (distance – 10,000)/ 350)

• Note: the Python function ceil rounds up its argument.


math.ceil(1.5) = 2
Solution
def taxi_fare(distance): # distance in metres
if distance <= 1000:
return 3.0
elif distance <= 10000:
return 3.0 +
(0.22*ceil((distance-1000)/400))
else:
return 8.06 +
(0.22*ceil((distance-10000)/350))

# check: taxi_fare(3300) = 4.32


Coping with Changes
• What if starting fare is increased to $3.20?
• What if 385 m is increased to 400 m?
Avoid Magic Numbers
• It is a terrible idea to hardcode constants
(magic numbers):
– Hard to make changes in future

• Define abstractions to hide them!


stage1 = 1000
stage2 = 10000
start_fare = 3.0
increment = 0.22 Better to make them all
block1 = 400 CAPS for “normal”
convention
block2 = 350

def taxi_fare(distance): # distance in metres


if distance <= stage1:
return start_fare
elif distance <= stage2:
return start_fare + (increment *
ceil((distance - stage1) /
block1))
else:
return taxi_fare(stage2) +
(increment * ceil((distance -
stage2) / block2))
How to I Manage My Own Code?
Let’s say I wrote some cool code

• And I save it to a file called

my_cool_package.py
Then I can use it for another file
• Another file: Same as the file name but
without “.py”
Or
• Another file:
Or
• Another file
Or But in general, it’s not a good
habit to name a
variable/function so short
• Another file that you cannot understand
what it does

You might also like