We have already seen two kinds of functions:
print
has the effect of printing stuff to the screen.math.sqrt(9)
is 3.0
Let's write our first function, piratically-themed in honour of the International Talk Like a Pirate Day.
def pirate_print(s):
'''Print the piratified version of the string s: "Ahoy! [s] Yarr!"
Arguments:
s -- a string
'''
print("Ahoy! " + s + " Yarrrrr!")
Here is what a function skeleton looks like:
def <function-name>(<parameters, separated by commans>):
'''Docstring -- a description of the function. The first sentence says what the function
should do, in the imperative.
Arguments:
<a list of the arguments/parameters, briefly describing what they are>
'''
<body of the function>
The docstring -- a string enclosed in triple quotes right after the first line of the function definition -- is conventionally included to make things more readable.
Let's now use the function. The proper terminology for using a function is calling a function.
pirate_print("I love CIV!")
pirate_print("Praxis too!!!")
What is happening there is that the argument ("I love CIV!"
, or "Praxis too!"
) gets assigned to the parameter s
. Then, the body of the function (in this case, print("Ahoy! " + s + " Yarrrrr!")
) gets executed.
This is the nice thing about functions -- we can write the once, but use them multiple times, as you see above.
Note that pirate_print()
is not like the functions we know from math -- we use it because it has an effect. The effic is printing stuff to the screen. But we don't use it to compute some value. Here is a function that can be used to compute a value.
def pirate_transform(s):
'''Return a "piratified" version of the string s, with "Ahoy!" in front,
and " Yarrrrr!" at the end
Arguments:
s -- a string
'''
piratified_s = "Ahoy! " + s + " Yarrrrr!"
return piratified_s
We have a new construct here -- the return
statement. The value of pirate_transform(s)
is whatever comes after the return
. For example,
pirate_transform("I love PHY!")
The value of pirate_transform("I love PHY!")
is 'Ahoy! I love PHY! Yarrrrr!'
. Note that this is different from what happenned before -- we can tell by the fact that there are quotes around the string that we are just looking at the value of an expression. It's as if we just said.
'Ahoy! I love PHY! Yarrrrr!'
The line pirate_transform("I love PHY!")
would not print anything to the screen if the line were part of the program. This line would, however:
print(pirate_transform("I love PHY!"))
We can go one step further:
print(pirate_transform(pirate_transform("I love PHY!")))
What happenned here? First, we evaluated pirate_transform("I love PHY!")
, and it's value turned out to be "Ahoy! I love PHY! Yarrrrr!"
. That means the line print(pirate_transform(pirate_transform("I love PHY!")))
has the same effect as
print(pirate_transform("Ahoy! I love PHY! Yarrrrr!"))
Note that pirate_transform(s)
is very similar to the functions that you know from school algebra, like $f(x) = x^2$. The value of $f(3)$ is 9 in the same way that the value of pirate_transform("hi!")
is "Ahoy! hi! Yarrrrr!"
.
Let's write one more function:
def has_roots(a, b, c):
'''Return True iff ax^2+bx+c=0 has real roots
[Note: Return True iff ... means, in Python (but not in math!) Return
True if ax^2+bx+c=0 has real roots and False otherwise]
Arguments:
a, b, c -- floats
'''
disc = b**2-4*a*c
#This is not the nicest way to write this -- we'll rewrite this function later
if disc >= 0:
return True
else:
return False
As you can see, a function can have more than one parameter. In this case, it has three -- a, b,
and c
. Let's use the function:
has_roots(1, 2, 3)
has_roots(1, 2, -3)
Let's now try to see what the value of the discriminant is:
disc
We cannot see the value of disc
. That's because disc
is a local variable inside the function has_roots
. You can think of local variables as "scratch work". After the function finishes running, all the local variables inside it get discarded.
The parameters are also local variables:
a
Let's now see another demonstration of this:
def plunder_grade():
grade = 0
if __name__ == '__main__':
grade = 95
plunder_grade()
print(grade)
The line grade = 0
defines a local variable grade. It gets discarded after plunder_grade()
is executed. The global value of grade
stays at 95.
I'll sometimes call the block of code under if __name__ == '__main__':
is called the "main block." For now, think of the line if __name__ == '__main__':
as just separating the function definitions from the code that uses the functions. We'll have more of an explanation soon.
plunder_grade()
has no parameters. It's defined as you see above, and it's called using ()
. Functions without parameters have their uses -- see print_grade()
below.
Global variables are variables defined outside of any function. For example, the variable grade
in the main block above is global. Here is an example:
def print_grade():
print(grade)
if __name__ == '__main__':
grade = 95
print_grade()
Since there is no local variable grade, the line print(grade)
prints the global variable grade
.
Here is how we can actually modify a global variable:
def actually_plunder_grade():
global grade
grade = 56
if __name__ == '__main__' :
grade = 95
actually_plunder_grade()
print(grade)
The line global grade
in the function actually_plunder_grade()
means that when we say grade = 56
, we mean we want to assign 56 to grade
.