Defining with def

Concepts covered: Functions

Uber prices a trip in cents: 250 for the pickup, 175 for every mile driven and 35 for every minute in the car. A program that quotes 3 trips with this formula writes the arithmetic out 3 times:

trip_1 = 250 + 3 * 175 + 12 * 35
print("Trip 1:", trip_1)
trip_2 = 250 + 8 * 175 + 25 * 35
print("Trip 2:", trip_2)
trip_3 = 250 + 1 * 175 + 6 * 35
print("Trip 3:", trip_3)

Every pair of lines repeats the same 3 multiplications with different numbers. When the pickup charge rises to 300, each copy needs its own edit, and a copy that goes unedited quotes the old price. A function stores the arithmetic once under a name, and every place that needs a quote calls that name.

The def statement

The smallest function takes no input at all. This one prints the 2 lines that open every Uber receipt:

def print_receipt_header():
    print("UBER RECEIPT")
    print("------------")

The first line is the header: the keyword def, the function's name, a pair of parentheses and a colon. Every indented line under it belongs to the function and is called its body. The body ends where the indentation ends, the same way the body of an if or a for does.

Running the def line creates the function and attaches the body to the name, and that is all it does: nothing inside the body runs. The body runs when the program calls the function, which means writing its name followed by parentheses. This program prints before the definition, prints after it, and then calls the function twice:

print("Program starts")

def print_receipt_header():
    print("UBER RECEIPT")
    print("------------")

print("Function defined, body not run yet")
print_receipt_header()
print_receipt_header()
print("Program ends")

Output:

Program starts
Function defined, body not run yet
UBER RECEIPT
------------
UBER RECEIPT
------------
Program ends

The 2 lines of the body printed twice, once per call, and nothing from the body appeared until the first call. Defining is a description of what will happen; calling is when it happens.

Define first, call second

Python runs a program from the top down, and a function's name does not exist until its def line has run. Calling the name on a line above the definition fails with a NameError, the same error a misspelled variable raises:

print_total()

def print_total():
    print("Total: 1195 cents")

Running it prints nothing. The call on line 1 runs before the definition has had a chance to, and Python stops with NameError: name 'print_total' is not defined. The message gives the type of failure and the name Python could not find. Moving the call below the def block fixes it, because by then the name exists.

Naming a function

A function name follows the rules for variable names: letters, digits and underscores, no spaces, no leading digit. Because a function does something, its name usually starts with a verb, so a reader of print_receipt_header() knows what will happen without opening the body.

Do
  • Start with a verb: print_receipt, check_balance, send_alert
  • Use lowercase words joined by underscores
  • Say what the body does, in full words
Avoid
  • Reuse a built-in name such as print or range for your own function
  • Abbreviate to the point of guessing: prh()
  • Give 2 functions names that differ by one letter

The fare formula as a function

The function below holds the Uber formula once. The names in its parentheses, miles and minutes, stand in for the numbers each trip supplies, and the next section covers how a call fills them. Step through the run and watch the body execute 3 times with 3 sets of numbers:

def print_fare(miles, minutes):
    cents = 250 + miles * 175 + minutes * 35
    print("Fare in cents:", cents)

print_fare(3, 12)
print_fare(8, 25)
print_fare(1, 6)
Fare in cents: 1195
Fare in cents: 2525
Fare in cents: 635

Three calls, one copy of the arithmetic. Raising the pickup charge to 300 now means editing one number on one line, and every trip quoted after that edit uses the new price.

How many lines does this program print?

def beep():
    print("beep")

for i in range(3):
    beep()
beep()

A working function needs both halves: the def keyword that opens the header, and a call that writes the name followed by parentheses. Leave out def and Python rejects the header line before anything runs. Write the name without its parentheses and the body stays silent, because the parentheses are what tell Python to run it. The call can sit anywhere below the definition, as many times as the program needs.

About this lesson

This section is part of the Functions: Beginner lesson on DataDriven, the home of data engineering. Lessons cover SQL, Python, Spark, data modeling and pipeline architecture, and each section pairs its explanation with worked examples and practice you run as you go.