Title: Review: Subroutines in Python
1Review Subroutines in Python
Subroutines (a.k.a. routines and procedures) are
a way to break a program up into named little
pieces. If we do it right, these pieces work
like building blocks that can be reused. Using
subroutines, we can solve a problem once and then
use that solution wherever we need it.
We have already been using subroutines that are
provided by Python raw_input(), randint(),
range(), etc. But as you know, we can also make
our own. Here's a very simple subroutine
definition def sayGoodbye() print "Goodbye, my
friend, goodbye. . . " return Then here's where
we use it (If we want to be fancy, we say we call
or invoke it) . . . if userResp
"no" sayGoodbye() . . .
2Subroutine Parameters
You provide information to a subroutine by
passing values to it. These values are called
parameters, or arguments. Weve been doing this
for a while numToGuess random.randint(3,20) u
serResp raw_input(Play again?) When you
define a subroutine, you have to provide a list
of any parameters that it requires. In the
subroutine say_goodbye() below, the parameter is
mood
def say_goodbye(mood) if mood "happy"
print "cheerio old chum!" elif mood
"grumpy" print "get lost, you bum"
else print "I don't know how to be", mood
return what will these do? say_goodbye("grumpy"
) say_goodbye("happy") say_goodbye("perplexed")
3One way to think about it. . .
- Think of the parameters as food for the
subroutine. You can think of the parentheses as
the subroutine's mouth - def feed_me(food)
- print "me like", food
- return
- feed_me("krill")
- feed_me("hamburgers")
4More on Parameters
- Subroutines can have multiple parameters
- def find_volume(length, width, height)
- vol length width height
- print "the volume is", vol
- return
- When you define subroutine parameters, you're
saying "Here is the information that this
subroutine needs to do its job", and you're
giving each piece of information a name so that
the subroutine can use it. - We say that the values for the parameters are
passed to the subroutine. The parameters are
identified by their position (or order) inside
the parentheses when the subroutine is called.
For example, when this call is made - find_volume(ln, 35, 2num)
- then inside the subroutine, length will have the
value of the variable ln, width will have the
value 35, and height will have a value 2 times
the value of the variable num.
5Make Sense?
def test(first, second) what will this
print? print first, second return first
"yo" second "pardner" test(first, second)
what will the line below print? print first,
second
What will be printed when we call main()?
6Wait, there's more. . .
- Within a subroutine, the parameters act like
variables that get their initial values from
whatever was passed in. - But like a bubble popping, those variables
disappear when the subroutine returns. Ponder
this
def test(first, second) what will this
print? print first, second first
"greetings" second "howdy" return first
"yo" second "pardner" test(first, second)
what will the line below print? print first,
second)
Do these two lines make any difference?
7Two kinds of subroutines
- A subroutine has a job that is, it does
something for us. There are two kinds of
subroutines - Some subroutines just do their job, and dont
give us back a value. - Examples
- turn_left()
- circle(50, 50, radius)
- 2) Some subroutines do something, and give us
back a value that we can use later on in our
program. We say that they return a value.
Subroutines that return values are frequently
called functions. - Examples
- numsBy3List range(1,100,3)
- userResp raw_input(Play again?)
- numToGuess random.randint(1,20)
- print "There are", len(myList), "items"
8Continuing the analogy. . .
- If subroutines can eat, it stands to reason that
they can also, shall we say, poop. That is,
they can give you something back after they've
done their job. More specifically, they can
return a value. - def fahrenheitToC(fahrenheitTemp )
- retval (fahrenheitTemp 32) 5 / 9.0
- return retval
- gtgtgt temp fahrenheitToC(212)
Means "return this value back to whoever called
us"
Whatever fahrenheitToC() returned will become
the new value of temp
(We've already seen this kind of thing with
raw_input(), which poops a string that the user
typed, and range(), which poops a list of
integers.)
Thanks to Kirby Urner for this illuminating
metaphor!
9 this subroutine makes an lth1gt heading for the
parameter text def makeHtmlHeading(text) return
"lth1gt" text "lt/h1gt" this subroutine
returns the larger of the two parameters def
max(val1, val2) if val1 gt val2 return
val1 else return val2 Using these
subroutines gtgtgt print makeHtmlHeading("Python
Hates Me") lth1gtPython Hates Melt/h1gt gtgtgt print
max(123,32) 123
Some return Examples
10 this subroutine returns the absolute value of
the parameter def abs(val) if val gt 0 return
val else return val subroutine returns a
Boolean value True if an odd number, otherwise
False def isOdd(val) if val 2 1 return
True else return False Using these
subroutines gtgtgt print abs(-17) 17 gtgtgt print
isOdd(17) True
More return Examples
11Returning Boolean Values
- Subroutines can return Boolean values True or
False - def startsWithVowel(word)
- if word0 in "aeiouAEIOU"
- return True
- else
- return False
- If the subroutine returns True or False, it can
be used in a condition for an if or while
statement - userWord raw_input("Gimme a word")
- if startsWithVowel(userWord)
- print userWord "starts with a vowel")
- else
- print userWord "does not start with a
vowel" - We saw this kind of thing in RUR-PLE
front_is_clear(), on_beeper() and the others are
just subroutines that return True or False
12Why return when youcan print?
- There is a big difference between a subroutine
printing a result and returning a result - when a subroutine prints a result, it is
displayed to the human user, but that does not
give the code that called the subroutine access
to the value the subroutine is a "black box" to
the rest of the program - when a subroutine returns a result, that value is
available to whatever called it to be saved in
a variable, used for further calculation, and so
forth
13Some Harder Examples
this subroutine returns the largest value in
a list of numbers def maxInList(numList) maxVa
l numList0 initial value has to be in the
list for nxt in numList if nxt gt
maxVal maxVal nxt return maxVal this
subroutine returns a count of the number of
times that the letter letter appears in the
string word. def count(word, letter) numTimes
0 for nxt in word if nxt letter
numTimes 1 return numTimes Using these
subroutines gtgtgt print max(1,44,932,34) 932 gtgtgt
print count("aardvark", "a") 3
14Something Useful readInt()
- def readInt(prompt)
- while True
- try
- ret int(raw_input(prompt))
- break
- except
- print "Please enter an integer"
- return ret
- Then your extra-credit 2 guessing game program
- could be written
- low readInt("Enter your low number")
- high readInt("Enter your high number")
- and so forth. . .
- See how parameters and return values make this
work?
15Something Useful a Quadratic Formula Solver
ax2 bx c 0
- import math
- pass in the values for the coefficients a, b,
and c - subroutine returns a list of the real roots,
- or an empty list if it has imaginary roots
- def quadratic(a, b, c)
- discriminant (b 2) - (4 a c)
- if discriminant lt 0
- return not ready for imaginary
numbers! - else
- r1 (-b math.sqrt(discriminant))/(2.0
a) - r2 (-b - math.sqrt(discriminant))/(2.0
a) - return r1, r2
16Call stack
- Question When a subroutine returns, where does
it return to? The subroutine doesn't know or
care but the Python runtime has to know where
to go next. - The address of the next line of code in the
caller is pushed onto the call stack before the
subroutine is called. - If that subroutine then calls another subroutine,
that second return address is pushed on top of
the previous one. - And so forth. . .
- When a subroutine returns, it returns to the
address on top of the stack. That address is
popped off the stack, exposing the one beneath it.
17Recursion
- returns factorial of num
- def factorial(num)
- if num lt 1
- return 1
- else
- return num factorial(num 1)
- what will this do?
- def blowup()
- return blowup()
- File "ltpyshell2gt", line 2, in blowup
- blowup()
- RuntimeError maximum recursion depth exceeded