home—info—labs—exams—hws
—D2L—MediaSamples/—breeze (snow day)—tutor/PIs
lab14-def
defining functions
putting statements inside `def`
Welcome back from the 4-day snow weekend!
Self-check:
How would you call the function blazz, giving it
43 and "yo!"?
You don't need to know that blazz is supposed to do with
that information!
alternate phrasing:
Alternatively, some people might say
“What is the blazz of 43 and yo!?”.
While you may get an error “blazz: name not known globally”,
you should not get “syntax error” — you can come up with
the correct syntax to call the function named “blazz”,
if that name were known.
In previous labs, we've developed the general rule for several problems:
How to compute…
- … the RU username (from a full-name)
- … the compression-factor of a nickname (given the fullname and the nickname)
- … the BMI (given the weight, height in whole feet, and any extra-inches)
- … the middle third of a story (from the full story)
Today, we'll make these into functions, so that (once you load the file)
they can be called just like sqrt or len
or any other function.
…We're constructing new lego blocks to use in the future!
And when we call that function, you won't need to remember all the thinking you put into it,
or how it works (no more than you need to know that sqrt uses Newton's method to
compute its answer).
This “functional abstraction” is one of the most fundamental ideas
in computer science,
and it's the key to breaking a large project (with millions of lines of code)
into manageable parts.
-
Syntax for defining a function call:
def namefunction( variable ):
expression…
return expression
|
important:
The indentation is important!
The statements must be indented underneath the def;
that's how python can tell which statements are inside the function,
from whatever statements you want after the function-definition.
We call the variable a “parameter”;
it's just like other variables except that
it gets initialized when somebody calls the function.
-
Example:
# ruUserName: string -> string
# Given a `fullName`, return a new RU Username for them.
#
def ruUserName( fullName ):
firstInit = substring(fullName, 0, 1)
startLast = string.find(fullName, " ") + 1
endLast = len(fullName)
lastName = substring( fullName, startLast, len(fullName) )
return string.lower( firstInit + lastName )
|
-
Actually, the above syntax isn't quite right; it doesn't allow for multiple inputs (like substring).
The real syntax for defining a function call:
def namefunction( variable [, variable]...):
statements...
return expression
|
-
Example:
# substring: string, int, int -> string
# Return characters extracted from `txt`,
# from index `start` up to (but not including) index `stop`.
#
def substring( txt, start, stop):
return txt[start:stop]
|
Two related but very distinct terms (don't confuse them!):
- argument: the value passed to a function.
Examples: "Mississippi", 3, and 7 are arguments in
substring("Mississippi", 3, 7);
25 is the argument in sqrt(21+4).
- parameter: a variable that occurs in a function definition;
it is initialized to hold whatever argument is passed in, when the function is called.
Examples:
The variable fullName, inside the function ruUserName, is
a parameter.
So are txt, start, and stop inside
the definition of substring.
Scope:
Note that even after you call ruUserName in the interactions window,
the variables firstInit etc. are not known in the interactions window.
Those variables are local to ruUserName.
Similarly, the parameter fullName is local to that function.
This notion of “local variables” is good — as we write our own code,
we don't need to worry about variables/parameter-names used inside functions
written by others (or, written by us two weeks ago).
We won't accidentally introduce a bug by happening
to name our own variable “start”.
Before/after
Before | After |
(input-info stored in variables 'manually', followed by expressions) |
(input-info passed in as parameters; re-usable! Expressions stored inside function.) |
# Change this one lines (only), to solve for a different fullname:
fullName = "Jay Leno"
fullName = "Ian Barland"
fullName = "James Fallon"
firstInit = substring(fullName, 0, 1)
startLast = string.find(fullName, " ") + 1
endLast = len(fullName)
lastName = substring( fullName, startLast, len(fullName) )
# the answer:
string.lower( firstInit + lastName )
|
|
# ruUserName: string -> string
# Given a `fullName`, return a new RU Username for them.
#
def ruUserName( fullName ):
firstInit = substring(fullName, 0, 1)
startLast = string.find(fullName, " ") + 1
endLast = len(fullName)
lastName = substring( fullName, startLast, len(fullName) )
return string.lower( firstInit + lastName )
# Three examples -- can call these from interaction (lower) pane:
# (And we don't need to go back and modify any existing lines!)
#
ruUserName( "Jay Leno" )
ruUserName( "Ian Barland" )
ruUserName( "James Fallon" )
|
|
TODO:
Go back to previous labs, and convert the various problems we solved into functions.
-
Make a file lab14.py, and paste in the code for substring,
as well as “import string”.
-
Caution:
In the steps below,
don't change your old files — instead,
let's open the old file, copy the code (Ctrl-C), and then
(re)open your current lab14.py, and paste (Ctrl-V).
I agree: it is rather annoying that JES doesn't let us have multiple files open at once.
-
From lab08,
create a function compression that takes in two inputs:
A (school's) fullname, and its nickname;
it returns the compression factor.
Examples:
compression( "Virginia Polytechnic Institute and State University of the World!", "Tech" ) returns 16.25, and
compression( "Radford University", "RU" ) returns 9.0.
Before | After |
(input-info stored in variables 'manually', followed by expressions) |
(input-info passed in as parameters; re-usable! Expressions stored inside function.) |
# Change these two lines (only), to solve for a different schoolName/nickName:
schoolName = "Virginia Polytechnic Institute and State University"
nickName = "Tech"
schoolName = "Radford University"
nickName = "RU"
schoolNameLen = len( schoolName )
nickNameLen = len( nickName )
# the answer:
float(schoolNameLen) / float(nickNameLen)
|
|
# compression: string, string -> float
# Return how much we compress the data, when we use a `nickName` instead of a full `schoolName`.
# E.g. a compression-factor of 3 means that we have used 1/3 the characters to communicate the same thing.
#
# TODO
( , ):
# Examples (you can all this from the lower (interactions) pane:
compression( "Virginia Polytechnic Institute and State University of the World!", "Tech" ) # Should be 16.25 (approx)
compression( "Radford University", "RU" ) # should be 9.0
|
|
-
Create a function bmi, which takes in a weight (in pounds),
a heigh (in whole feet) and any extra-inches, and returns the BMI:
bmi(220,3,3) returns (approximately) 100,
and bmi(220,6,6) returns (approximately) 25.
Before | After |
(input-info stored in variables 'manually', followed by expressions) |
(input-info passed in as parameters; re-usable! Expressions stored inside function.) |
# Change these three lines (only), to solve for a different person:
weightLbs = 220
wholeFeet = 3
extraInches = 3.2
weightLbs = 220
wholeFeet = 6
extraInches = 6.4
weightLbs = 165
wholeFeet = 5
extraInches = 7
LBS_PER_KG = 2.2
IN_PER_FT = 12
CM_PER_IN = 2.54
weightKg = weightLbs / LBS_PER_KG
heightIn = float(wholeFeet)*IN_PER_FT + extraInches
heightCm = heightIn * CM_PER_IN
heightM = heightCm/100
# the answer:
BMI = weightKg / pow(heightM,2)
|
|
# Examples -- can be called from the interactions (lower) pane:
bmi(220, 3, 3.2) # should be 100 (approx)
bmi(220, 6, 6.4) # should be 25 (approx)
bmi(165, 5, 7)
|
|
- From lab08-variable-practice—variables: practice, recall how we computed the
middle third of story.
Make a function which takes a string, and returns its middle third.
Before | After |
(input-info stored in variables 'manually', followed by expressions) |
(input-info passed in as parameters; re-usable! Expressions stored inside function.) |
TODO (you can look back at lab08-variable-practice—variables: practice for the
code, but you should be able to figure it out for yourself too!)
# Change this lines (only), to solve for a different piece of text:
story = "Once upon a time, a frog lived happily ever after."
# …any intermediate steps/code…
# the answer — middle third:
|
|
TODO
|
home—info—labs—exams—hws
—D2L—MediaSamples/—breeze (snow day)—tutor/PIs