Programming: Simon Scheidegger
Programming: Simon Scheidegger
Lecture 3
Simon Scheidegger
Roadmap of today
1. Functions
3. Recursions
1. Functions
How we learned to code so far
Until now
We have covered language mechanisms.
We know how to write different files for each computation.
We consider each file to be some piece of code.
We assume that each code is a sequence of instructions.
Problems with this approach
it is easy for small-scale problems.
however, it messy for larger problems.
it hard to keep track of details.
how do you know the right info is supplied to the right part of code.
Good programming practice
More code is not necessarily a good thing.
Measure good programmers by the amount of functionality.
→ Introduce functions.
→ Recycling.
Decomposition
(generating a joint output)
Functions
In programming, it is useful to divide the code into modules that
are self-contained
used to break up code
intended to be reusable
keep code organized
keep code coherent
Today: in this lecture, achieve decomposition with functions
Later: achieve decomposition also with classes
Functions → Abstractions
In programming, think of a piece of code as a black box.
do not (always) need to see details.
do not (always) want to see details.
hide tedious coding details.
function characteristics:
has a name
has parameters (0 or more)
has a docstring (optional but recommended → allows re-use)
has a body
returns something
Example: Fibonacci-sequence
https://en.wikipedia.org/wiki/Fibonacci_number
for n > 1.
One has F2 = 1.
Functions: definition
demo/example_1.py
Functions: definition (II)
demo/example_1.py
How to call Functions
(from Terminal)
demo/example_1.py
def fib(n):
"""Returns the nth Fibonacci number."""
a=0
b=1
for i in range(n):
tmp = a
a=a+b
b = tmp
return a
Function call
How to call Functions
from another File
demo/example_1b.py
print("Function call from another code: fib(5) =", ex.fib(5)) #call the function
def g(y):
print(x)
print(x+1)
x=5
g(x)
print(x)
def h(y):
pass
#x += 1 #leads to an error without line `global x` inside h
x=5
h(x)
print(x)
More on Scope
demo/example_2c.py
def g(x):
def h():
x = 'abc'
x=x+1
print('in g(x): x =', x)
h()
return x
x=3
z = g(x)
If still uncertain...
http://www.pythontutor.com/
More Notes on Functions
Functions always have a return value
Without a return statement the value is simply None
Functions are objects
Can be used like any other object (list of functions, ...)
Function arguments are passed by assignment
More precisely call by object reference
No function overloading
Functions can’t have the same name (even if the number of
arguments differ)
Operator overloading works, later...
Once more: NO return STATEMENT
demo/example_3.py
def is_even_without_return( i ):
"""
Input: i, a positive int
Does not return anything
"""
print('without return')
remainder = i % 2
is_even_without_return(3)
Python returns the value None, if no return given
represents the absence of a value
Once more: NO return STATEMENT
demo/example_3b.py
def is_even_with_return( i ):
"""
Input: i, a positive int
Returns True if i is even, otherwise False
"""
print('with return')
remainder = i % 2
return remainder == 0
is_even_with_return(3)
print(is_even_with_return(3) )
Python returns the value None, if no return given
represents the absence of a value
Recycling helps – short Code
demo/example_3c.py
Call the same # Use the is_even function later on in the code
function many print("All numbers between 0 and 20: even or not")
times for i in range(20):
if is_even(i):
print(i, "even")
else:
print(i, "odd")
return vs. print
“return” “print”
def func_a():
print('inside func_a')
def func_b(y):
print('inside func_b')
return y
def func_c(z):
print('inside func_c')
return z()
print(func_a())
print(5+func_b(2))
print(func_c(func_a))
arguments can take on any type, even functions
Functions: lambda expressions
Small anonymous functions can be created with the lambda keyword
Example:
Convenient to define small functions
Lambda-expressions
demo/example_6.py
def apply(func,x):
return func(x)
x = apply(lambda z: z**2,2.)
print(x)
Recall: Coding
Some very important conventions/rules:
Use 4-space indentation, and no tabs
Wrap lines so that they don’t exceed 79 characters
Use blank lines to separate functions and classes, and larger
blocks code inside functions
Use docstrings: documentation
No fancy encodings, even in comments!
PEP8: https://www.python.org/dev/peps/pep-0008/
Read it carefully...
2. Lists, Tuples, Dictionaries
Compound data types
So far, we have seen variable types: int, float, bool,string.
We want now to introduce new compound data types
(data types that are made up of other data types)
Tuples (similar to strings – sequences of something)
Lists (similar to strings – sequences of something)
idea of aliasing
idea of mutability
idea of cloning
Mutable vs. Immutable types
Mutable types
Can change their contents / members
lists, dicts, user-defined types
Immutable types
Cannot change their contents / members
most built-in types (int, float, bool, str, tuple)
Lists
Is an ordered sequence of information, accessible by index
a list is denoted by square brackets, [ ]
a list contains elements
usually homogeneous (i.e., all integers)
can contain mixed types (not common)
list elements can be changed → list is mutable
How to use Lists
demo/example_9.py
More on Lists
Add elements to a List
add elements to end of list with L.append(element)
mutates the list!
L = [2,1,3]
L.append(5) → L is now [2,1,3,5]
what is the dot?
lists are Python objects, everything in Python is an object
objects have data
objects have methods and functions
to combine lists together use concatenation, + operator,
to give you a new list
mutate list with L.extend(some_list)
L1 = [2,1,3]
L2 = [4,5,6]
L3 = L1 + L2 → L3 is [2,1,3,4,5,6], L1, L2 unchanged
L1.extend([0,6]) → mutated L1 to [2,1,3,0,6]
Remove Elements from a List
demo/example_15.py
delete element at a specific index with del(L[index])
remove a specific element with L.remove(element)
looks for the element and removes it
if element occurs multiple times, removes first occurrence
if element not in list, gives an error
Recall: lists are mutable
They behave differently than immutable types
is an object in memory
variable name points to object
any variable pointing to that object is affected
How to Change elements in a List
Recall that lists are mutable!
assigning to an element at an index changes the value
L = [2, 1, 3]
L[1] = 5
L is now [2, 5, 3], note this is the same object L
[2,1,3]
Iterating over a List
compute the sum of elements of a list
common pattern, iterate over list elements
( ) ( )
Please note:
→ list elements are indexed 0 to len(L)-1
→ range(n) goes from 0 to n-1
Iterate over Lists
demo/example_14.py
def sum_elem_method1(L):
total = 0
for i in range(len(L)):
total += L[i]
return total
def sum_elem_method2(L):
total = 0
for i in L:
total += i
return total
print(sum_elem_method1([1,2,3,4]))
print(sum_elem_method2([1,2,3,4]))
http://www.pythontutor.com/
demo/example_16.py
Cloning a List
create a new list and copy every element using
heavy_metal = heavy[:]
Cast Strings to Lists
demo/example_17.py
L=[9,6,0,3]
print(sorted(L))
More on Assignments
demo/example_8.py
Be careful!
Passing Function Arguments – no
return in function
Consider
and
Passing Function Arguments (II)
no return in function
Consider
and
Passing function arguments:
pass by assignment – no return in function
In Python
Variables are just names (labels)
Names “bind” to an object when assigned to
Assignment does not copy data
Passing function arguments:
pass by assignment – no return in function
In Python
Variables are just names (labels)
Names “bind” to an object when assigned to
Assignment does not copy data
Passing function arguments:
pass by assignment – no return in function
In Python
Variables are just names (labels)
Names “bind” to an object when assigned to
Assignment does not copy data
Passing function arguments:
pass by assignment – no return in function
In Python
Variables are just names (labels)
Names “bind” to an object when assigned to
Assignment does not copy data
Passing function arguments:
pass by assignment – no return in function
In Python
Variables are just names (labels)
Names “bind” to an object when assigned to
Assignment does not copy data
Passing function arguments:
pass by assignment – no return in function
In Python
Variables are just names (labels)
Names “bind” to an object when assigned to
Assignment does not copy data
Passing function arguments:
pass by assignment – no return in function
In Python
Variables are just names (labels)
Names “bind” to an object when assigned to
Assignment does not copy data
Passing function arguments:
pass by assignment – no return in function
In Python
Variables are just names (labels)
Names “bind” to an object when assigned to
Assignment does not copy data
Passing function arguments: pass by
assignment
In Python
Variables are just names (labels)
Names “bind” to an object when assigned to
Assignment does not copy data
Passing function arguments: pass by
assignment
In Python
Variables are just names (labels)
Names “bind” to an object when assigned to
Assignment does not copy data
Passing function arguments: pass by
assignment
In Python
Variables are just names (labels)
Names “bind” to an object when assigned to
Assignment does not copy data
Passing function arguments: pass by
assignment
In Python
Variables are just names (labels)
Names “bind” to an object when assigned to
Assignment does not copy data
Passing function arguments: pass by
assignment
In Python
Variables are just names (labels)
Names “bind” to an object when assigned to
Assignment does not copy data
Passing function arguments: pass by
assignment – the code
demo/example_7.py
def incr(x):
x += 1
x=0
incr(x)
print(x)
def incr_first(x):
x[0] += 1
x = [0,1,2]
incr_first(x)
print(x)
More Built-in types: Tuples
Tuples is more or less like a list but cannot be changed
(i.e., are immutable)
Use parentheses instead of brackets
Support similar operations as lists
Tuples
demo/example_10.py
Tuples are an ordered sequence of elements, can mix element types
# empty tuple
te = ()
t = (2,”HEC",3)
t[0] → evaluates to 2
conveniently used to swap variable values
used to return more than one value from a function
>>> for a, b in x:
... print "First", a, "then", b
First 1 then 2
First 3 then 4
First 5 then 6
More Built-in types: Dictionaries
If we want to manage a data collection of computer users, we can store
information so far e.g., using separate lists for every info
names = ['Tom', 'Keith', 'Marry', 'Megan']
grade = [6.0, '4.5, 5.2, 4.9]
course = ['Programming', 'Physics', 'Econometrics', 'Economics']
A separate list for each item
Each list must have the same length
info stored across lists at same index, each index refers to info for a
different person
Multiple Lists
Messy if have a lot of different info to keep track of
Must maintainmany lists and pass them as arguments
Must always index using integers
Must remember to change multiple lists
Basic functionality of Dictionaries
Nice to index item of interest directly (not always int)
Nice to use one data structure, no separate lists
similar to indexing into a list, looks up the key ‘Keith’
returns the value associated with Keith
If key isn’t found, you get an error
Tom 6
Keith 4.5
Marry 5.2
Megan 4.9
demo/example_24.py
Some operations on Dictionaries
demo/example_24.py
Add an entry
grades['Freddy'] = 4.9
Test if key in dictionary
'Tom' in grades → returns True
'Daniel' in grades → returns False
Delete an entry
del(grade['Mary'])
More operations on Dictionaries
demo/example_24.py
Get an iterable that acts like a tuple of all keys
# access via []
x['a'] == 1
demo/example_19.py
Dictionary keys and values
Values
Any type (immutable and mutable)
Can be duplicates
Dictionary values can be lists, even other dictionaries!
keys
Must be unique
Immutable type (int, float, string, tuple,bool)
actually need an object that is hash-table, but think of as
immutable as all immutable types are hash-table
Be careful with float type as a key
no order to keys or values!
demo/example_24.py
Lists versus dict
List Dict
Dictionaries – summary
3. Recursions
A recursion
Algorithmically: a way to design solutions to problems
by divide-and-conquer or decrease-and-conquer
Reduce a problem to simpler versions of the same
problem.
Semantially: a programming technique where a function calls
itself
In programming, the goal is to NOT have infinite recursion
Must have 1 or more base cases that are easy to solve
Must solve the same problem on some other input with the
goal of simplifying the larger problem input.
Iterative algorithms (for loops)
demo/example_20.py
Looping constructs (while and for loops) lead to
iterative algorithms.
Can capture computation in a set of state variables that
update on each iteration through loop.
print mult_a(2,10)
The alternative – a recursive way
demo/example_21.py demo/example_22.py
The recursive step
Think how to reduce the problem to a simpler/smaller version of
same problem
a*b = a + a + a + a + ... + a (n times)a
Base case
Keep reducing = a + a + a + a + ... + a (1 + n-1 times)a
the problem until we reach a = a + a * (b-1) recursive reduction
simple case that can
be solved directly
when b = 1, a*b = a
def mult_iter(a, b):
if b == 1:
def factorial(n):
return a
if n == 1:
else:
return 1
return a + mult_iter(a, b-1)
else:
return n*factorial(n-1)
print mult_iter(1,10)
print(factorial(10))
What’s going on in factorial?
def fact(n):
if n == 1:
return 1
else:
return n*fact(n-1)
print(fact(4))
Iteration versus Recursion
recursion may be simpler, more intuitive
recursion may be efficient from programmer point of view
recursion may not be efficient from computer point of view
A famous Example:
The Fibonacci sequence
Fibonacci numbers
Leonardo of Pisa (aka Fibonacci) modeled the following
challenge
Newborn pair of rabbits (one female, one male) are put in a pen.
Rabbits mate at age of one month
Rabbits have a one month gestation period
Assume rabbits never die, that female always produces one new
pair (one male, one female) every month from its second month
on.
→ How many female rabbits are there at the end of one year?
Fibonacci Sequence – the code
https://en.wikipedia.org/wiki/Fibonacci_number
def F(n):
if n == 0: return 0
elif n == 1: return 1
else: return F(n-1)+F(n-2)
def fib(n):
if n == 1:
return 1
elif n == 2:
return 2
else:
return fib(n-1) + fib(n-2)
Questions?