return
statement¶Inside a function the return
causes immediate termination of the function's execution, and returns to point of invocation.
A return
is implicitly executed at the end of each function, if an explicit return is not used.
In the example below the getWishes()
function returns explicitly a string
value, whereas the happyNewYear()
function returns None
implicitly.
def getWishes():
return 'Happy New Year!'
def wishHappyNewYear(wishes):
print(wishes)
wishes = getWishes()
print('Returned:', wishHappyNewYear(wishes))
Happy New Year! Returned: None
A returned value, from a function should:
import math
def circleArea(radius):
'''Returns the area of a circle given its radius.'''
return math.pi * radius**2
unitArea = circleArea(1.0)
print('unit area:', unitArea)
print( 'area:', circleArea(5.0) )
unit area: 3.141592653589793 area: 78.53981633974483
Often the return value from a function depends on some conditional logic, e.g. an if
statement.
In those cases make sure that every possible path has a return
.
def compareWrong(a, b):
'''Return -1, 0, 1 to indicate ordering of a and b
Descending: if a < b, returns -1
Same: if a == b, returns 0
Ascending: if a > b, returns 1'''
if a < b:
return -1
elif a > b:
return 1
print( '1 == 1:', compareWrong(1,1) )
1 == 1: None
def compare(a, b):
'''Return -1, 0, 1 to indicate ordering of a and b
Descending: if a < b, returns -1
Ascending: if a > b, returns 1
Same: if a == b, returns 0
'''
if a < b:
return -1
elif a > b:
return 1
else:
return 0
print( '1 == 1:', compare(1,1) )
print( '1 < 2 :', compare(1,2) )
print( '2 > 1 :', compare(2,1) )
1 == 1: 0 1 < 2 : -1 2 > 1 : 1
As you develop more complicated functions and programs, it will be very beneficial to you if you take an incrementatl approach to your problem solving workflow.
Start small, i.e. focus on one small aspect of the solution, verify each step with print statements and once happy with result, refactor if you can.
Try to follow these steps basically:
Start with a working program and make small incremental changes to it. That way you will know when an errors creeps in.
To aid in debugging, use local variables, which you can then print and check.
See whether or not refactoring makes sense; keep readability in mind.
def distance(x1, y1, x2, y2):
return 0.0
print( distance(1, 2, 4, 6) )
0.0
import math
def distance(x1, y1, x2, y2):
dx = (x2 - x1)
dy = (y2 - y1)
# check point
print(dx, dy)
d = math.sqrt(dx**2 + dy**2)
# check point
print(d)
return d
print( distance(1, 2, 4, 6) )
3 4 5.0 5.0
import math
def distance(x1, y1, x2, y2):
dx = (x2 - x1)
dy = (y2 - y1)
return math.sqrt(dx**2 + dy**2)
# Verify with known values
print( 'd =', distance(1, 2, 4, 6) )
d = 5.0
You can define a function that calls upon other functions to do the actual work. This technique is called composition and reduces/eliminates redundancy and its associated potential errors.
Assume you want to compute the area of a circle given two points; the center of the circle and a point on its perimeter.
def circleAreaTwoPoints(xc, yc, xp, yp):
return circleArea( distance(xc, yc, xp, yp) )
print('area:', circleAreaTwoPoints(10, 10, 13, 14) )
area: 78.53981633974483
The relational operators (<
, <=
, >
, >=
) and equality operators (==
, !=
) return a Boolean
(True
or False
) result.
It is more readable if you assign such results to a boolean type variable.
Boolean functions can be used to hide complicated boolean expressions, thus making your code easier to write and understand.
Boolean functions should start with is to indicate their True
/ False
nature.
def isDivisible(num, by):
'''Returns True if by devides into num, False otherwise'''
return num % by == 0
print( '6 % 3?', isDivisible(6, by=3) )
print( '6 % 4?', isDivisible(6, by=4) )
print( '2 % 3?', isDivisible(2, by=3) )
6 % 3? True 6 % 4? False 2 % 3? False
def isBetween(num, lower, upper):
'''Return True is lower <= num <= upper, False otherwise.'''
# return lower <= num and num <= upper
# or even better
return lower <= num <= upper
print( '1 <= 2 <= 3?', isBetween(2, 1, 3) )
print( '3 <= 2 <= 4?', isBetween(2, 3, 4) )
1 <= 2 <= 3? True 3 <= 2 <= 4? False
Recursion is a great technique for solving problems. The solution is actually expressed in terms of the problem itself, a cyclical answer of sorts.
We'll start with the solution to the factorial of $n$, expressed as $n!$.
By definition we have:
$0! = 1$
$n! = n(n-1)!$
def factorial(n):
# First we shall check for a proper value.
if not isinstance(n, int):
print('Argument must be an integer.')
return None
elif n < 0:
print('Negative value not allowed.')
return None
# Base case.
if n == 0:
print('n =', n, ': base case')
return 1
else:
# Step down
print('n =', n, ': step down')
# Recursive step
f = n * factorial(n - 1)
# Step up
print('f =', f, ': step up')
# Backtrack
return f
print( '\n5! =', factorial(5), '\n' )
print( 'one! =', factorial('one'), '\n' )
print( '-4! =', factorial(-4) )
n = 5 : step down n = 4 : step down n = 3 : step down n = 2 : step down n = 1 : step down n = 0 : base case f = 1 : step up f = 2 : step up f = 6 : step up f = 24 : step up f = 120 : step up 5! = 120 Argument must be an integer. one! = None Negative value not allowed. -4! = None
The fibonacci series is defined as follows:
$fibonacci(0) = 0$
$fibonacci(1) = 1$
$fibonacci(n) = fibonacci(n - 1) + fibonacci(n - 2)$ for $n >= 2$
def fibonacci(n):
'''Returns the nth value in the fibonacci series.'''
# Reject all non-integer values.
if not isinstance(n, int):
print('n must be an integer value.')
return None
elif n < 0:
print('Negative values not allowed.')
return None
if n == 0:
# Base case.
print('n =', n, ': base case')
return 0
elif n == 1:
# Base case.
print('n =', n, ': base case')
return 1
else:
# Recursive step
print('n =', n)
fib1 = fibonacci(n - 1)
print('n =', n)
fib2 = fibonacci(n - 2)
return fib1 + fib2
print( '\nfibonacci(5): ', fibonacci(5) )
n = 5 n = 4 n = 3 n = 2 n = 1 : base case n = 2 n = 0 : base case n = 3 n = 1 : base case n = 4 n = 2 n = 1 : base case n = 2 n = 0 : base case n = 5 n = 3 n = 2 n = 1 : base case n = 2 n = 0 : base case n = 3 n = 1 : base case fibonacci(5): 5
Notice how much redundant computations are performed in just trying to determine fibonacci(5).
We can improve the solution by:
a) using iteration rather than recursion and
b) storing each evaluated result, when first encounted, in a dictionary (see later on). Each subsequent occurence will then be retieved rather than recomputed.
Create a separate Python source file (.py) in VSC to complete each exercise.
Define four functions to carry out each of the four mathematical operations, add, substract, multiply, and divide. Each function should accept two parameters and return the corresponding result.
Call each function and print the results as:
2 + 4 = 6
2 - 4 = -2
2 * 4 = 8
2 / 4 = 0.5
A palindrome is a word that is spelled the same backward and forward, like "noon" and "redivider". Recursively, a word is a palindrome if the first and last letters are the same and the remaining middle is a palindrome.
The following are functions that take a string argument and return the first, last, and middle letters:
def first(word):
return word[0]
def last(word):
return word[-1]
def middle(word):
return word[1:-1]
We shall study these techniques later on in the course.
Type these functions into a script and test them out. What happens if you call middle()
with a string with two letters? One letter? What about the empty string, which is written as ''
and contains no letters?
Write a recursive function called is_palindrome()
that takes a string argument and returns True
if it is a palindrome and False
otherwise. Remember that you can use the built_in function len()
to check the length of a string.
A number, $a$ is a power of $b$ if it is divisible by $b$ and $a/b$ is a power of $b$. Write a recursive function called is_power()
that takes parameters a
and b
and returns True
if a
is a power of b
. Note: you will have to think about the base case.
The greatest common divisor (GCD) of a and b is the largest number that divides both of them with no remainder.
One way to find the GCD of two numbers is base on the observation that if $r$ is the remainder when $a$ is divisible by $b$, then $gcd(a, b) = gcd(b, r)$. As a base case, we can use $gcd(a, 0) = a$.
Write a recursive function called gcd()
that takes parameters a
and b
and returns their greatest common divisor.