ChristCoded

the course / the basics

Functions: a dream goes in, its meaning comes out

Pharaoh dreamed of seven fat cows and seven thin ones, and Joseph told him what they meant. A function works the same way: something goes in, it does its work, and it hands something back. Learn def, parameters, return, and how to call a function again and again.

And Joseph said unto Pharaoh, The dream of Pharaoh is one: God hath shewed Pharaoh what he is about to do. The seven good kine are seven years; and the seven good ears are seven years: the dream is one. And the seven thin and ill favoured kine that came up after them are seven years; and the seven empty ears blasted with the east wind shall be seven years of famine. — Genesis 41:25–27 (KJV)

Pharaoh had a dream nobody in Egypt could explain: seven fat cows came up out of the river, then seven thin ones that ate them up. Joseph didn’t add anything of his own; he was clear that the meaning came from God (verse 16). He listened to the dream and gave back its meaning: seven years of plenty, then seven years of famine.

Something goes in, the work is done, something comes back. In programming, that’s a function.

Defining a function

def interpret(dream):
    if dream == "seven fat cows":
        return "seven years of plenty"
    else:
        return "seven years of famine"
  • def means “define”: we’re making a new function.
  • interpret is its name. You’ll use the name to run it later.
  • dream inside the parentheses is a parameter: the input. It’s a variable that only exists inside the function.
  • The indented lines are the body: the work. Here it’s an if / else.
  • return hands a value back to whoever asked, and the function stops there.

Defining a function doesn’t run it. It’s like writing down how to interpret a dream: nothing happens until someone actually brings you one.

Calling a function

print(interpret("seven fat cows"))
print(interpret("seven thin cows"))
seven years of plenty
seven years of famine

When Python reaches interpret("seven fat cows"):

  1. It jumps into the function, with dream set to "seven fat cows".
  2. It runs the body. The if is True, so it reaches return "seven years of plenty".
  3. It comes back, and the whole call interpret("seven fat cows") is replaced by that value, which print shows.

The second call does the same work with a different input, so a different answer comes back.

Keeping what comes back

The value a function returns is a value like any other: you can put it in a variable.

meaning = interpret("seven fat cows")
print(meaning.upper())    # SEVEN YEARS OF PLENTY

Write it once, call it many times

This is why functions exist. The rule for reading the dream is written in one place, and you can use it as many times as you want. If you ever need to change the rule, you change it once, and every call gets the new version.

def greet(name):
    print("Peace be with you, " + name)

r = greet("Joseph")    # shows: Peace be with you, Joseph
print(r)               # None

print shows text on the screen. return hands a value back to the code that called the function. A function without return hands back None, Python’s word for “nothing”.

The same idea in JavaScript

function interpret(dream) {
  if (dream === "seven fat cows") {
    return "seven years of plenty";
  } else {
    return "seven years of famine";
  }
}

console.log(interpret("seven fat cows"));   // seven years of plenty

It’s everywhere

Call What happens
search("sheep") a search term goes in, results come back
send(message) your message goes out
save(photo) the photo is stored for later

Every button you tap in an app is wired to a function.

Common mistakes

  • Forgetting the parentheses when calling: interpret is the function itself; interpret("...") runs it.
  • Forgetting the colon after def interpret(dream) or the indentation of the body.
  • Printing instead of returning, then trying to use the result: you get None.
  • Code after return in the same block never runs: return leaves the function right away.
  • Calling before defining: Python reads top to bottom, so def has to come first.

Try it

  1. Write def double(n): that returns n * 2. What does double(double(5)) give?

  2. Joseph told Pharaoh to store up a fifth of the harvest in the good years (Genesis 41:34). Write def fifth(harvest): that returns harvest / 5, and call it with 100.

  3. Change interpret so that "seven good ears" also returns "seven years of plenty". (Hint: or.)

    Answers
    def double(n):
        return n * 2
    print(double(double(5)))   # 20
    
    def fifth(harvest):
        return harvest / 5
    print(fifth(100))          # 20.0
    
    def interpret(dream):
        if dream == "seven fat cows" or dream == "seven good ears":
            return "seven years of plenty"
        else:
            return "seven years of famine"

Reflect

Joseph was clear: “It is not in me: God shall give Pharaoh an answer of peace” (Genesis 41:16). He didn’t invent the meaning; he passed on what he was given, faithfully. And because he did, Egypt stored grain in the good years and had bread in the hard ones, and so did his own family. A gift that’s received, then handed on.