Practice Writing Functions

5 minute read

Purpose

We want to get good at writing functions

  • Abstraction!
  • Divide and conquer
  • We are going to do a lot with classes - that needs functions

References for this lecture

Problem Solving with Algorithms and Data Structures using Python, Section 1.12: https://runestone.academy/ns/books/published/pythonds/Introduction/DefiningFunctions.html

Also see Chapter 3 of Think Python( https://greenteapress.com/thinkpython2/html/thinkpython2004.html )

Here’s a function that isn’t very useful

Discuss: Why is this a bad function?

def f_to_c():
    fahrenheit_temp = float(input("Enter a temperature in Fahrenheit: "))
    celsius_temp = (fahrenheit_temp-32)*(5/9)
    print("That's",celsius_temp,"in Celsius") 
f_to_c()

If we instead write the function like this:

def f_to_c(fahrenheit_temp):
    celsius_temp = (fahrenheit_temp-32)*(5/9)
    return celsius_temp

then we can use it in many different contexts

#....
if f_to_c(value_from_file) < 0:
    freezing_days += 1
#....

Let’s draw some pictures to remind ourselves how parameters and return values work.

Another Example

def calculate_pay(wage,hours):
    if hours <= 40:
        pay = wage*hours
    else:
        overtime_hours = hours-40
        pay = (wage*40) + (wage*1.5*overtime_hours)

    print("Total pay:",pay)

vs.

def calculate_pay(wage,hours):
    if hours <= 40:
        pay = wage*hours
    else:
        overtime_hours = hours-40
        pay = (wage*40) + (wage*1.5*overtime_hours)

    return pay

employee_database = [("Lola Howell",17.65,42),("Nicolas Wagner",14.05,38),("Marlene Ramos",15.80,40)] #etc

for employee in employee_database:
    issue_paycheck(employee[0],calculate_pay(employee[1],employee[2]))

Rule of thumb

Put all your user interaction (input, print, etc.) into one function like main, user_interface, etc.

Most other functions shouldn’t have any print or input statements at all!

In-Class Coding Activity: Infinite Monkey Theorem

A monkey hitting random keys on a typewriter for an infinite amount of time will eventually type the complete works of Shakespeare.

Chimpanzee_seated_at_typewriter.jpg

You are going to write some functions which simulate this. If we generate a bunch of random strings, how close will they get to a line of Shakespeare?

After class, copy whatever code your group worked on, and put it into file called infinite_monkey.py, and continue working through the problems on your own computer - the result will be submitted for Assignment 2.

This exercise is adapted from the example in Section 1.12 of the book, though note that the specific expectations of how each function works are different.

Group Activity Problem 1

Run the following code example. In the notes section below, describe what the code does. Also, answer the following questions in the notes: What happens when you change the 9 to a different number? What is the type of alphabet?

alphabet = "abcdefghijklmnopqrstuvwxyz "
print( alphabet[9] )

Notes:

write your notes here

Group Activity Problem 2

Run the following code example multiple times. In the notes section below, describe what the code does. Also, answer the following questions in the notes: What is the purpose of the import statement? Is it possible for a 26 to be printed by this code? What happens when you change the 26 to a different number?

import random

print( random.randint(0,26) )

Notes:

write your notes here

Group Activity Problem 3

Run the following code example multiple times. In the notes section below, describe what the code does. Also, answer the following questions in the notes: What effect would changing the 26 to a different number have on this code? Is there a better way to write this code that avoids having to hard-code the literal 26 into the code?

import random

alphabet = "abcdefghijklmnopqrstuvwxyz "
print( alphabet[ random.randint(0,26) ] )

Notes:

write your notes here

Group Activity Problem 4

The code below turns the above code into a function. Write the function call that will cause this function to run multiple times. Notice that this function prints its result, but to be more useful, it should instead return it. Go ahead and fix that, and then adjust your call to the function so that it will print the returned value.

import random

def random_letter():
    alphabet = "abcdefghijklmnopqrstuvwxyz "
    print( alphabet[ random.randint(0,26) ] )

Notes:

write your notes here

Group Activity Problem 5

Run the following code example multiple times. In the notes section below, describe what the code does. Also, answer the following questions in the notes: What effect does changing the number 28 to another number have? What is the type of the random_string variable? What is the purpose of the += operator in this code?

random_string = ""
for i in range(28):
    random_string += random_letter()
print(random_string)

Notes:

write your notes here

Group Activity Problem 6

Create a function called random_text based on the code from the previous problem. It should allow a number to be passed to the function as an argument, and it should return a random string with that many characters in it. It should work if we test it with some code like this:

#write your code for the definition of the random_text function here

print( random_text(28) ) #generates random text with 28 characters in it, e.g., lzqnnzantpgfmmkziadskr tzwez
print( random_text(5) ) #generates random text with 5 characters in it, e.g., bnhou
print( random_text(50) ) #e.g., hiep hwx tfkvbjjyqycaefvsbqipaylnqeiujhccvvpvelsxk

Notes:

write your notes here

Group Activity Problem 7

Write a function called score that will tell us how close some random text is to some goal text. It should work as follows:

  • take two arguments with strings to be compared
  • loop through the indexes of one of the strings (you can assume the two strings have the same length)
  • compare each character in one string to the corresponding character in the other string
  • add 1 to an accumulator variable when you find the same letter at the same position in both strings
  • return the number of characters that match

You should be able to call it like this

#write your code for the definition of the score function here

print( score("test string 1","test string 2") )  #should print 12

goal_shakespeare = "methinks it is like a weasel"
random_test_string = random_text(len(goal_shakespeare)) #generate a random string with the same length as the goal string
print( score(random_test_string, goal_shakespeare) ) #print how many characters they have in common

Notes:

write your notes here

Group Activity Problem 8

Write a function called monkey_experiment that takes in a goal string (e.g., "methinks it is like a weasel") and a number of iterations as an argument. Run the experiment for that many iterations, and return a tuple with the highest-scoring text that was generated along with the score that it got.

That is, your function should have a loop that does something like this many many times (i.e., the number of times that is passed in as an argument):

random_test_string = random_text(len(goal_shakespeare))
print( score(random_test_string, goal_shakespeare) ) 

Hint: You should have a variable for keeping track of the best score you’ve found so far, and another variable for saving the string that is associated with that best score. Whenever you find one with a better score, update these variables.

You should also test your function with several different goal strings and numbers of iterations - something like this:

#write your code for the definition of the monkey_experiment function here

print(monkey_experiment("methinks it is like a weasel",100000))
print(monkey_experiment("methinks it is like a weasel",100))
print(monkey_experiment("brevity is the soul of wit",100000))
print(monkey_experiment("to be",100000))
print(monkey_experiment("to be",200000))
print(monkey_experiment("to be",500000))

When I tested my function, I got results that look like this for the above tests:

('yetha  xqtynpxgfkkoaedweasf ', 8)
('ktsnmgoknxlkldupuce jgvnaael', 5)
('vfcmitu emgthe h svidavhhs', 7)
('lo be', 4)
('tf by', 3)
('toube', 4)

Notes:

write your notes here