Here’s what we’ll cover (based on suggestions/questions from students in the session):
First line:
def
()
(my_param)
(a,b,c)
:
Examples:
def celsiusToFarenheit(celsius):
def totalEnrollment(studentInfo):
def isPrime(my_integer):
def printGreeting():
def firstRoot(a,b,c):
Why? What is happening?
The first thing to realize is that when we type something like this:
celsiusToFarenheit(20) - 1
This is evaluated by first running the code inside the function definition of celsiusToFarenheit
then replacing the words celsiusToFarenheit(20)
with the return value.
So:
celsiusToFarenheit(20) - 1
becomes:
68.0 - 1
Because celsiusToFarenheit(20)
when you run it, returns the value 68.0
Now: What happens in the case of cToF?
The thing to understand is that every python function that doesn’t encounter a return
statement, when it reaches the end of the code, it does return None
.
So:
def cToF(celsius):
print( ((celsius / 5.0) * 9.0) + 32.0 )
But really, inside of Python’s mind, it looks like this:
def cToF(celsius):
print( ((celsius / 5.0) * 9.0) + 32.0 )
return None
We didn’t type the return None
. Python put that in for us (whether we like it or not!)
So, when we have:
cToF(20) - 1
The cToF(20)
is evaluated: meaning we go do the code inside the function defintion of cToF
, with celsius
having the value 20
.
And we end up printing the value 68.0
on the screen and then returning None
.
So we get:
None - 1
Which is an error!
We can see that directly if we type it in:
Note that these two expressions give the same error!
Answer: sometimes you really do just want to put some output on the screen, and you don’t want your function to immediately end!
Consider this function that can print a conversion table from celsius to farenheit:
def cToF(celsius):
print( ((celsius / 5.0) * 9.0) + 32.0 )
def tempTable(first, last, step):
print ("C","F")
for temp in range(first,last+1,step):
print(temp, celsiusToFarenheit(temp))
tempTable(0,100,10)
If we replaced the occurences of print
inside the tempTable
function with return
, we wouldn’t get the result we want.
Remember that return
ends a function immediately. If we want to go through every iteration of the loop, we need print
Here’s a link: https://realpython.com/python-formatted-output/
What if we wanted a nicer table?
Instead of:
We want all of the numbers to line up nicely in columns?
I can change the width of the fields from 5 to 4 and get a more compact table. Here I also changed the step value from 10 to 5
We’ll come back later and cover that in more detail.
I just wanted you to see a nicely formatted table as part of answering “why would we ever use print”.
Typically when we are using print, it’s because we are trying to format some nice output for a human to read.
Whereas, when we use return, are returning the result of a computation that we might want to use somewhere else in the program.
It’s when the same symbol has different meanings in different contexts.
So, for example:
x = 3 + 5
Here the +
means add. 3 plus 5.
But:
name = "Phill"
school = "UC San Diego"
message = name + " is teaching for " + school
Here, the +
means “string concatenation”. So, the +
can have different meanings in different contexts.
There’s even another meaning of +
: concatenating lists:
In the same way %
means mod in one context (i.e. remainder after division)
x = 121 % 10 #result is 1
y = 121 % 11 #result is 0
But in another context, it means string formatting:
print('%5d %5d' % ( temp, celsiusToFarenheit(temp) ) )
Here, the operand on the left of the %
is a format string. The %d
means “decimal number” and %5d
means a “decimal number with width of 5”.
The operand on the right of the %
is a tuple containing all of the values that are going to be printed by the “percent thingies”.
Each percent thingy (i.e. %5d
or %5s
for a string) is replaced by one of the values in the tuple.)
We sometimed “hard code” values in a function definition, like this.
def tempTableHardCoded():
print ('%4s %4s' % ("C","F") )
print ('%4s %4s' % ("-----","-----") )
for temp in range(0,101,10):
# print(temp, celsiusToFarenheit(temp))
print('%4d %4d' % ( temp, celsiusToFarenheit(temp) ) )
Here in the range
for the for loop, 0, 101, 10 are the hard coded values.
It means that this funciton is not very flexible. We always, always, get the same table. If we want a different table, too bad.
By contrast, this function definition has parameters: first, last, step
def tempTable(first, last, step):
print ('%4s %4s' % ("C","F") )
print ('%4s %4s' % ("-----","-----") )
for temp in range(first,last+1,step):
# print(temp, celsiusToFarenheit(temp))
print('%4d %4d' % ( temp, celsiusToFarenheit(temp) ) )
Now, we can do a variety of function calls, and get a variety of results!
tempTable(-40,40,10)
tempTable(0,100,5)
tempTable(0,40,2)
etc
Here’s the results:
> tempTable(-40,40,10)
C F
----- -----
-40 -40
-30 -22
-20 -4
-10 14
0 32
10 50
20 68
30 86
40 104
> tempTable(0,100,5)
C F
----- -----
0 32
5 41
10 50
15 59
20 68
25 77
30 86
35 95
40 104
45 113
50 122
55 131
60 140
65 149
70 158
75 167
80 176
85 185
90 194
95 203
100 212
> tempTable(0,40,2)
C F
----- -----
0 32
2 35
4 39
6 42
8 46
10 50
12 53
14 57
16 60
18 64
20 68
22 71
24 75
26 78
28 82
30 86
32 89
34 93
36 96
38 100
40 104
>
Two ways to count from 1 to 10
print('''
*** counting 1 to 10 with a for loop ***
''')
for i in range(1,11):
print(i)
print('''
*** counting 1 to 10 with a while loop ***
''')
i = 1
while (i<=10):
print(i)
i+=1
Output:
*** counting 1 to 10 with a for loop ***
1
2
3
4
5
6
7
8
9
10
*** counting 1 to 10 with a while loop ***
1
2
3
4
5
6
7
8
9
10
Here is a more practical program that uses a while loop. This calculates factors of an integer:
import math
def factor_limit(my_number):
'''
largest number I need to check that could
be a factor of my_number
'''
return int(math.sqrt(my_number))
def first_factor(my_number):
for i in range(2,factor_limit(my_number)+1):
if my_number % i == 0:
return i # we found a factor!
return my_number
def get_factors(my_number):
factors = []
factor = first_factor(my_number)
factors.append(factor)
rest_of_number = my_number // factor
# We use a while loop here, because we
# can't predict how many times the loop is
# needed
while(rest_of_number > 1):
factor = first_factor(rest_of_number)
factors.append(factor)
rest_of_number = rest_of_number // factor
return factors
Sample output:
> get_factors(127)
[127]
> get_factors(128)
[2, 2, 2, 2, 2, 2, 2]
> get_factors(121)
[11, 11]
> get_factors(360)
[2, 2, 2, 3, 3, 5]
> get_factors(36)
[2, 2, 3, 3]
>