MGU Computer Science Series — Programming with Python
Part III: Functions and Program Design
Definitions · Calls · Execution · Tracing · Reuse
Chapter 11 of 30
11
MGU Computer Science Series  ·  Programming with Python  ·  Library Textbook Edition

Chapter 11:
Defining and Calling
Functions

Naming a block of code, calling it by name, and tracing execution as it jumps into a function and back — the foundation of organized programs

■ Part III of VII ■

■ 10 Sections  •  Chapter 11 of 30 ■

Builds on Parts I and II — values, expressions, conditionals, and loops

Chapter Purpose and Learning Objectives

You have now written programs that read input, make decisions, and repeat work with loops. Those programs work. But if you look back at some of them, you may notice something uncomfortable: they are starting to grow. A program that validates input, calculates a result, formats the output, and checks for errors can become forty or fifty lines long before it feels finished — and that is still a small program. Real programs are often thousands of lines.

How do professional programmers keep large programs from becoming a tangled mess? One of the most important answers is functions.

A function is a named block of code that does a specific job. You define a function once, give it a name, and then call that name whenever you need that job done. Functions let you break a large program into smaller, named pieces. They let you reuse code without copying it. They let you test one part of a program independently from the rest. And they make programs far easier to read, because a well-named function tells you what it does without making you read every line of it.

Chapter Focus

This chapter introduces functions. You will learn how to define a function, how to call a function, how Python transfers execution into a function and back, and how functions help you organize programs. The chapter focuses on reading and tracing functions before writing complicated ones. That sequence — read first, trace carefully, then write — is one of the most important habits in programming.

10Sections
6Objectives
10Key Terms
30Total Chapters

Learning Objectives

By the end of this chapter, you should be able to:

  1. 1Explain what a function is and why functions matter.
  2. 2Define a function using def.
  3. 3Call a function and explain what happens when you do.
  4. 4Trace execution through a program that uses functions.
  5. 5Write simple functions that perform clear, specific tasks.
  6. 6Recognize and avoid the most common function mistakes.

Sections at a Glance

Sections 11.1 – 11.3
The Basics: Why Functions Exist, How to Define Them, How to Call Them
Motivation · Definitions · Calls

Why Functions Matter

Imagine you are writing a program that prints a welcome message at the start and a goodbye message at the end. You also print a separator line — a row of dashes — to divide sections of the output. You decide the separator is twenty dashes long.

Here is one way to write that program:

print("Welcome to the Grade Calculator")
print("--------------------")
print("Enter your scores below.")
print("--------------------")
score1 = float(input("Score 1: "))
score2 = float(input("Score 2: "))
average = (score1 + score2) / 2
print("--------------------")
print("Your average is:", average)
print("--------------------")
print("Thank you for using the Grade Calculator.")

This works. But notice that print("--------------------") appears four times. If you decide to change the separator to thirty dashes, or to use equals signs instead, you must find every copy and change each one. If you miss one, the output will look inconsistent.

Now imagine that same separator is used in ten different places across a two-hundred-line program. Finding and changing every copy becomes tedious — and error-prone.

A function solves this problem. You define the separator logic once, give it a name, and call that name whenever you need it:

def print_separator():
    print("--------------------")

print("Welcome to the Grade Calculator")
print_separator()
print("Enter your scores below.")
print_separator()
score1 = float(input("Score 1: "))
score2 = float(input("Score 2: "))
average = (score1 + score2) / 2
print_separator()
print("Your average is:", average)
print_separator()
print("Thank you for using the Grade Calculator.")

Now the separator is defined in one place. If you want to change it, you change the function definition and every call to the function immediately uses the new version.

This example shows only one reason functions matter. Here is a fuller list:

Reason 1
Avoiding Repetition
Code that appears in many places is code that must be maintained in many places. A function lets you write that code once and reuse it.
Reason 2
Organizing Programs
A program that is one long sequence of statements is hard to navigate. A program organized into named functions is easier to read because each function has a job that its name describes.
Reason 3
Testing Pieces Independently
When something goes wrong in a large program, you need to find where it went wrong. If your program is organized into functions, you can test each function separately to find the problem.
Reason 4
Reading Before Writing
When you encounter a function call, you know what that function is supposed to do just from its name. You do not have to read every line of the function to understand the overall program flow.
Reason 5
Building Larger Programs
Every program larger than a few dozen lines uses functions. Knowing how to define and call functions is not optional. It is one of the core skills of programming.

Function Definitions

A function definition tells Python that a named block of code exists and what that block of code should do. Python does not run the code inside a function definition immediately. It remembers the definition so it can run the code later, when you call the function.

The syntax for a function definition in Python is:

def function_name():
    statement
    statement
    ...

Let us look at each part:

def is a keyword that tells Python you are defining a function. It stands for "define."

function_name is the name you choose for the function. You follow the same naming rules as variable names: use lowercase letters, separate words with underscores, choose a name that describes what the function does.

(): is a pair of parentheses followed by a colon. The parentheses are required even if the function takes no input. The colon signals that an indented block follows.

The indented statements below the def line form the function body — the code that runs when the function is called. All of those statements must be indented consistently. Python uses indentation to know where the function body starts and ends.

Here is a complete, simple function definition:

def greet_user():
    print("Hello!")
    print("Welcome to the program.")

This defines a function named greet_user. When called, it prints two lines. Python reads this definition and remembers it, but it does not print anything yet.

Here is another example:

def show_instructions():
    print("Instructions:")
    print("1. Enter your name when prompted.")
    print("2. Enter a number between 1 and 10.")
    print("3. Press Enter to continue.")

This function prints four lines of instructions. Again, defining it does not run it.

Important Distinction

Defining a function and calling a function are two different actions. A definition creates the function. A call runs it. If you define a function but never call it, the code inside it never runs.

Function Calls

A function call tells Python to run the code inside a function definition. You call a function by writing its name followed by parentheses:

greet_user()

When Python reaches this line, it pauses where it is, jumps into the function body, runs every statement inside the function, and then returns to the line after the call. Execution continues from there.

Here is a complete program that defines and then calls two functions:

def greet_user():
    print("Hello!")
    print("Welcome to the program.")

def show_instructions():
    print("Instructions:")
    print("1. Enter your name when prompted.")
    print("2. Enter a number between 1 and 10.")
    print("3. Press Enter to continue.")

greet_user()
show_instructions()
print("Program starting now.")
Output
Hello! Welcome to the program. Instructions: 1. Enter your name when prompted. 2. Enter a number between 1 and 10. 3. Press Enter to continue. Program starting now.

Notice the order of events:

  1. Python reads the definition of greet_user and remembers it.
  2. Python reads the definition of show_instructions and remembers it.
  3. Python reaches greet_user() and jumps into that function.
  4. Python prints the two lines inside greet_user.
  5. Python returns to the line after greet_user().
  6. Python reaches show_instructions() and jumps into that function.
  7. Python prints the four lines inside show_instructions.
  8. Python returns to the line after show_instructions().
  9. Python prints "Program starting now."

You can call a function as many times as you want:

def print_separator():
    print("--------------------")

print_separator()
print("Section One")
print_separator()
print("Section Two")
print_separator()
Output
-------------------- Section One -------------------- Section Two --------------------

The function is defined once but called three times. Each call runs the same code.

Sections 11.4 – 11.6
Writing Functions Well: Names, Indentation, and Execution Order
Naming · Code Blocks · Reading vs. Running

Function Names

Choosing good function names is part of writing good programs. A well-named function makes the code that calls it much easier to read.

Use lowercase letters and underscores. Python function names follow the same convention as variable names: print_separator, greet_user, show_instructions, calculate_total, display_menu.

Use verbs or verb phrases. Functions do things, so their names should describe what they do. print_separator is better than separator. calculate_total is better than total. show_instructions is better than instructions.

Be specific. display_main_menu is more informative than display_menu if there are multiple menus in your program. validate_age is more informative than check or validate.

Avoid abbreviations that obscure meaning. calc_avg might seem efficient, but calculate_average is clearer and Python has no length limit on names.

Here are some examples of weak versus stronger function names:

Weak NameStronger Name
f()format_output()
do_stuff()process_scores()
helper()print_separator()
x()calculate_tip()
run()display_welcome_message()
Why This Matters

When you read a program that uses well-named functions, the calls almost read like English sentences describing what the program does. That readability is not a luxury — it is a sign of good design.

Code Blocks and Indentation

In Python, the body of a function is defined by indentation. Every statement inside the function must be indented by the same amount — conventionally four spaces — relative to the def line.

def show_status():
    print("Checking status...")
    print("All systems ready.")

Both print statements are indented four spaces. They are both inside the function body.

The function body ends when indentation returns to the previous level:

def show_status():
    print("Checking status...")
    print("All systems ready.")

print("This is outside the function.")

The last print statement is not indented, so it is not part of show_status. It runs at the module level, not inside any function.

Indentation Errors Are Common and Important

If you mix spaces and tabs, or indent some lines more than others, Python will raise an IndentationError. Here is an example of a mistake:

def show_status():
    print("Checking status...")
  print("All systems ready.")   # Wrong: only 2 spaces

Python will complain that this is unexpected indentation. Both lines inside a function must use the same indentation level.

A function body must contain at least one statement. An empty function body causes a SyntaxError. If you want to define a function that does nothing (perhaps as a placeholder), use the pass keyword:

def placeholder_function():
    pass

pass is a valid statement that does nothing. It satisfies Python's requirement for a non-empty function body.

Execution Order with Functions

Understanding how Python executes a program with functions requires a clear mental model. There are two important phases:

Two Phases
How Python handles function definitions and calls
  • Phase 1Reading definitions. When Python reads your file from top to bottom, it encounters def statements and records the function definitions. It does not run the code inside them yet.
  • Phase 2Running calls. When Python encounters a function call, it pauses the current execution, jumps to the function body, runs the statements inside, and then returns to where it left off.

This distinction explains something that confuses many beginners: you can define a function after you call it in some languages, but in Python the definition must appear before the call is reached during execution. Consider this program:

greet_user()    # This call comes first in the file

def greet_user():
    print("Hello!")

Python reads the file from top to bottom. When it reaches greet_user(), it has not yet read the definition of greet_user. The result is a NameError:

Error
NameError: name 'greet_user' is not defined

The fix is to place the definition before the call:

def greet_user():
    print("Hello!")

greet_user()    # Now the definition exists before the call runs

This works correctly.

A common and well-organized pattern is to define all your functions at the top of the file, and then write the main program logic at the bottom. Some programmers go further and define a special function called main() that contains the main program logic, and call it at the very end:

def greet_user():
    print("Hello!")
    print("Welcome to the program.")

def show_instructions():
    print("Enter a number between 1 and 100.")

def main():
    greet_user()
    show_instructions()
    number = int(input("Your number: "))
    print("You entered:", number)

main()
A Clean Convention

This pattern — define functions, then call main() at the bottom — is a clean convention for organizing programs. You will see it often in professional Python code.

Avoiding Repetition with Functions

One of the most practical uses of functions is eliminating repeated code. Repeated code is sometimes called code duplication. It creates two problems: it makes the program longer than it needs to be, and it means you must maintain the same logic in multiple places.

Here is a program with significant repetition:

# Without functions
print("Student 1")
print("-" * 20)
name1 = input("Name: ")
score1 = float(input("Score: "))
print(f"Result: {name1} scored {score1}")
print()

print("Student 2")
print("-" * 20)
name2 = input("Name: ")
score2 = float(input("Score: "))
print(f"Result: {name2} scored {score2}")
print()

print("Student 3")
print("-" * 20)
name3 = input("Name: ")
score3 = float(input("Score: "))
print(f"Result: {name3} scored {score3}")
print()

The same pattern appears three times. If you want to change the format of the result line, you must change it in three places.

A function captures that pattern once:

def process_student(number):
    print(f"Student {number}")
    print("-" * 20)
    name = input("Name: ")
    score = float(input("Score: "))
    print(f"Result: {name} scored {score}")
    print()

process_student(1)
process_student(2)
process_student(3)

This version is shorter, clearer, and easier to maintain. If you decide to change the output format, you change the function definition once and all three students get the new format.

Looking Ahead

You will learn more about how functions like process_student receive information like the student number in Chapter 12, which covers parameters and arguments in detail.

Tracing Function Calls

Tracing a program that uses functions means following execution step by step across function definitions and calls. This is an important skill. When a program stops doing what you expect, being able to trace which functions ran and in what order is often the key to finding the problem.

Method
How to trace a program with functions
  • Step 1Start at the top of the file. When you reach a def statement, note the function name but do not trace its body yet. The body does not run until the function is called.
  • Step 2Continue until you reach a function call. Write down which function is being called.
  • Step 3Jump to the body of that function. Trace each statement in order.
  • Step 4When the function body ends (or you reach a return statement), return to the line immediately after the call.
  • Step 5Continue from there.

Let us trace a complete example step by step:

def print_line():
    print("----------")

def greet():
    print_line()
    print("Hello, welcome!")
    print_line()

print("Program starts.")
greet()
print("Program ends.")

Trace:

StepLocationAction
1Line 1def print_line — definition noted, body not run
2Line 4def greet — definition noted, body not run
3Line 8print("Program starts.") — prints Program starts.
4Line 9greet() — jump to greet body
5Line 5print_line() — jump to print_line body
6Line 2print("----------") — prints ----------
7(end of print_line)return to greet, line after print_line() call
8Line 6print("Hello, welcome!") — prints Hello, welcome!
9Line 7print_line() — jump to print_line body
10Line 2print("----------") — prints ----------
11(end of print_line)return to greet, line after second print_line() call
12(end of greet)return to main program, line after greet() call
13Line 10print("Program ends.") — prints Program ends.
Complete Output
Program starts. ---------- Hello, welcome! ---------- Program ends.

Notice that print_line is called twice (once inside greet, which is itself called once). Each call runs the same body.

Tracing Calls Within Calls

Tracing one function calling another is the same process — jump into the called function, run it, return. You will see functions calling other functions frequently as programs grow. The trace logic does not change; it just adds more jumps.

Section 11.10
Avoiding Trouble: Common Function Mistakes
Six Mistakes Every Beginner Should Recognize

Common Function Mistakes

Beginners encounter certain function errors repeatedly. Knowing them in advance helps you recognize them quickly when they appear.

Mistake 1 — Calling the Function Before Defining It
show_menu()      # NameError: name 'show_menu' is not defined

def show_menu():
    print("1. Start")
    print("2. Quit")

Python has not seen the definition when it reaches the call. Move the definition above the call, or define all functions at the top and call them at the bottom.

Mistake 2 — Forgetting the Parentheses in a Call
def greet():
    print("Hello!")

greet    # This does NOT call the function

Writing just greet without parentheses refers to the function as an object — it does not call it. Nothing is printed. The call requires parentheses: greet().

Mistake 3 — Indentation Errors in the Function Body
def display_total():
    total = 100
  print("Total:", total)    # IndentationError: unexpected indent

All statements in the function body must use the same indentation. Here print is indented only two spaces while total is indented four. Python raises an IndentationError.

Mistake 4 — Code That Should Be Inside the Function Is Outside It
def calculate_area():
    length = float(input("Length: "))
    width = float(input("Width: "))

area = length * width          # NameError: 'length' is not defined
print("Area:", area)

The last two lines are at the module level, not inside the function. length and width are defined inside calculate_area and are not accessible outside it. You will learn exactly why in Chapter 13 (Scope). For now, the fix is to make sure the code belongs inside the function body if it uses variables defined there.

Mistake 5 — Confusing Definition and Call
def show_total():       # This defines the function but does not run it
    print("Total: 0")

# Forgot to add: show_total()

The function is defined but never called, so nothing is printed. Always check that you have both a definition and at least one call if you intend the function to run.

Mistake 6 — Printing Inside a Function and Expecting a Value Back
def double(number):
    print(number * 2)    # Prints the result

result = double(5)       # result is None, not 10
print(result)            # Prints None

This is a preview of a common confusion you will study carefully in Chapter 12. Functions that only print do not send a value back to the caller. The variable result receives None — Python's way of saying "nothing." To get a value back from a function, you must use return, which Chapter 12 covers in full.

Organizing a Program with Functions

This worked example shows how to take a program written as one long block of code and reorganize it using functions. The process has two stages: understand the original program, then redesign it.

Original Program (No Functions)

print("=" * 35)
print("   QUIZ SCORE REPORT")
print("=" * 35)

name = input("Student name: ")
score1 = float(input("Quiz 1 score: "))
score2 = float(input("Quiz 2 score: "))
score3 = float(input("Quiz 3 score: "))

average = (score1 + score2 + score3) / 3

print("-" * 35)
if average >= 90:
    grade = "A"
elif average >= 80:
    grade = "B"
elif average >= 70:
    grade = "C"
elif average >= 60:
    grade = "D"
else:
    grade = "F"

print(f"Student: {name}")
print(f"Scores: {score1}, {score2}, {score3}")
print(f"Average: {average:.1f}")
print(f"Grade: {grade}")
print("=" * 35)

This program works fine, but it is one solid block. Let us identify the distinct jobs it does:

  1. Print the header
  2. Collect the student name and three scores
  3. Calculate the average
  4. Determine the letter grade
  5. Print the results

Each of these is a candidate for a function:

Redesigned Program (With Functions)

def print_header():
    print("=" * 35)
    print("   QUIZ SCORE REPORT")
    print("=" * 35)

def print_separator():
    print("-" * 35)

def print_footer():
    print("=" * 35)

def collect_scores():
    name = input("Student name: ")
    score1 = float(input("Quiz 1 score: "))
    score2 = float(input("Quiz 2 score: "))
    score3 = float(input("Quiz 3 score: "))
    return name, score1, score2, score3

def calculate_average(score1, score2, score3):
    return (score1 + score2 + score3) / 3

def determine_grade(average):
    if average >= 90:
        return "A"
    elif average >= 80:
        return "B"
    elif average >= 70:
        return "C"
    elif average >= 60:
        return "D"
    else:
        return "F"

def print_results(name, score1, score2, score3, average, grade):
    print_separator()
    print(f"Student: {name}")
    print(f"Scores: {score1}, {score2}, {score3}")
    print(f"Average: {average:.1f}")
    print(f"Grade: {grade}")
    print_footer()

def main():
    print_header()
    name, score1, score2, score3 = collect_scores()
    average = calculate_average(score1, score2, score3)
    grade = determine_grade(average)
    print_results(name, score1, score2, score3, average, grade)

main()

The redesigned main() function reads almost like a plain-English summary of the program:

  • Print the header
  • Collect scores
  • Calculate the average
  • Determine the grade
  • Print the results

You do not have to read the body of any other function to understand what the program does. That clarity is the goal.

Note

This example uses return values and parameters — concepts covered in Chapter 12. Do not worry about those details right now. Focus on the structure: separate jobs get separate functions, and main() calls them in order.

Chapter Summary

A function is a named block of code that performs a specific task. Defining a function with def creates a reusable piece of code that you can call by name. When you call a function, Python pauses the current execution, runs every statement in the function body, and returns to the line after the call.

Key Terms

function
A named block of code that performs a specific task and can be called by name.
function definition
The def statement and its indented body, which creates a function and names it.
function body
The indented block of statements inside a function definition.
function call
A line of code that invokes a function by writing its name followed by parentheses, causing Python to run the function body.
def
The Python keyword that begins a function definition.
execution
The process of running program statements in order.
call stack
The record Python keeps of where execution is at any moment, including which functions have been called and where to return when each one ends.
indentation
The consistent leading spaces that define code blocks in Python. Function bodies must be indented.
code duplication
Repeating the same or similar code in multiple places, which makes programs harder to maintain.
pass
A Python keyword used as a placeholder statement in an empty code block.
main() function
A convention where the main program logic is placed inside a function named main that is called at the end of the file.

Code Reading

Read each program carefully. Answer the questions that follow without running the code.

Exercise 1
def say_hello():
    print("Hello!")

def say_goodbye():
    print("Goodbye!")

say_hello()
say_goodbye()
say_hello()

a) How many times is say_hello called?
b) How many times is say_goodbye called?
c) What is the complete output of this program?

Exercise 2
def display_stars():
    print("* * * * *")
    print("* * * * *")
    print("* * * * *")

print("Before")
display_stars()
print("After")

a) What is the complete output?
b) If you moved print("Before") to after display_stars(), what would the output be?

Exercise 3
def line_a():
    print("Line A")
    line_b()
    print("Back in A")

def line_b():
    print("Line B")

line_a()
print("Done")

a) In what order do the lines print?
b) Which function calls which other function?
c) Write out the complete output.

Exercise 4
def show_menu():
    print("1. Add item")
    print("2. Remove item")
    print("3. Quit")

show_menu()
choice = input("Choice: ")
print("You chose:", choice)
show_menu()

a) How many times does show_menu run?
b) What does the program do between the two calls to show_menu?
c) If the user types 2, what is the complete output?

Exercise 5

Read this function definition. Then answer: what does this function do, and what would happen if you wrote just print_box instead of print_box() to call it?

def print_box():
    print("+--------+")
    print("|        |")
    print("+--------+")

Code Tracing

For each program, trace execution by filling in a table showing each step, which line runs, and what output is produced. Do this carefully before checking with Python.

Tracing Exercise 1
def step_one():
    print("Step one complete.")

def step_two():
    print("Step two complete.")

def step_three():
    print("Step three complete.")

print("Starting process.")
step_one()
step_two()
step_three()
print("Process finished.")

Fill in this table:

StepLineOutput Produced
1def step_one()(none — definition only)
2def step_two()(none — definition only)
3def step_three()(none — definition only)
4print("Starting process.")Starting process.
5step_one() — jump to body
6Inside step_one: print(...)
7Return from step_one
.........

Complete the table for all remaining steps.

Tracing Exercise 2
def show_title():
    print("--- Report ---")

def show_body():
    show_title()
    print("Body content here.")
    show_title()

show_body()

a) List every function call in the order it happens.
b) Write out the complete output.
c) How many times does show_title actually run?

Tracing Exercise 3
def alpha():
    print("alpha start")
    beta()
    print("alpha end")

def beta():
    print("beta start")
    gamma()
    print("beta end")

def gamma():
    print("gamma")

alpha()

Trace all steps. Write the complete output. This is a three-level function call chain — trace it carefully.

Predict the Output

Write the exact output (including blank lines if any) that each program produces. Then verify with Python.

Predict 1
def message():
    print("Hello from the function.")

print("Before the call.")
message()
print("After the call.")
Predict 2
def repeat_me():
    print("I repeat.")

repeat_me()
repeat_me()
repeat_me()
Predict 3
def outer():
    print("outer 1")
    inner()
    print("outer 2")

def inner():
    print("inner")

outer()
outer()
Predict 4
def do_nothing():
    pass

print("Before")
do_nothing()
print("After")
Predict 5
def section(title):
    print(f"=== {title} ===")

section("Introduction")
section("Main Content")
section("Conclusion")

Debugging Practice

Each program below contains one or more errors. Identify each error, explain what is wrong, and write a corrected version.

Debug 1
def greet()
    print("Hello!")

greet()

What error does Python report? What is missing?

Debug 2
def show_info():
    print("Name: Alex")
        print("Score: 95")    # Error on this line

show_info()

What is wrong with this code? Correct the indentation.

Debug 3
welcome()

def welcome():
    print("Welcome to the program!")

What error occurs? Why? How do you fix it?

Debug 4
def display_result():
    print("Result: 42")

display_result    # Missing something

What is missing? What does this line do as written? What should it be?

Debug 5
def calculate():
    value = 10 * 5

result = value
print(result)

What error does Python report when you try to run this? Why can't result = value access value? (Hint: think about where value is defined.)

PracticeShort Programming Tasks

Complete each task by writing a Python program. Test your programs before submitting.

  1. Task 1. Define a function called print_dashes that prints a row of 25 dashes. Call it three times to produce three rows of dashes.
  2. Task 2. Define a function called display_welcome that prints a welcome message of your choice. Define a second function called display_goodbye that prints a goodbye message. Write a main program that calls both functions, with some input or processing in between.
  3. Task 3. Define a function called print_countdown that prints: 3, 2, 1, Go! on separate lines. Call this function three times in your program.
  4. Task 4. Define functions called section_one, section_two, and section_three. Each function should print a brief message identifying which section it is. Then write a main() function that calls all three in order and call main() at the end of your program.
  5. Task 5. A student writes this program and is confused about why show_result never seems to do anything. Find the problem and fix it:
    def show_result():
        print("The result is 42.")
    
    print("Starting program.")
    show_result
    print("Program done.")
  6. Task 6. Write a program with a function called print_menu that displays at least four menu options (they can be for any kind of program you imagine). Call print_menu twice: once at the start of the program and once at the end. Between the two calls, print a line that says "Processing your choice...".
  7. Task 7 (Challenge). Write a program that defines five small functions and calls them inside a main() function to produce a neatly formatted "mini report" of your own design. The report can be about anything: a sports team, a class schedule, a recipe, a game score, or something else. Use at least one function that you call more than once.
Mixed ReviewCumulative Review

These exercises review skills from earlier chapters alongside the function skills from this chapter.

  1. Review 1. Write a program that defines a function called celsius_to_fahrenheit that prints a conversion table header. Then, using a for loop (from Chapter 9), print the Celsius and Fahrenheit values for every 10 degrees from 0 to 100. (You do not need to put the loop inside the function — you can call the function before the loop.)
  2. Review 2. Write a program that asks the user to enter a number using input() (Chapter 4) and uses an if/elif/else statement (Chapter 6) to classify it. Then define a function called print_result that takes no parameters but prints a decorative border line before and after the result. Call print_result once the classification is done.
  3. Review 3. The following program uses a while loop (Chapter 8) to keep asking for input. It also calls a function. Trace the execution and write the complete output for a run where the user enters 5, then 3, then -1.
    def show_value(value):
        print(f"Value entered: {value}")
    
    total = 0
    number = int(input("Enter a number (-1 to quit): "))
    while number != -1:
        show_value(number)
        total = total + number
        number = int(input("Enter a number (-1 to quit): "))
    
    print(f"Total: {total}")

Common Misconceptions

Misconception 1
"Defining a function runs it."
False. A function definition only tells Python what the function should do when called. The body does not run until the function is called.
Misconception 2
"You only need to call a function once."
Not true. You can call a function as many times as you need. One of the main points of functions is that you can reuse them.
Misconception 3
"A function with no return statement does nothing useful."
Not quite. Functions that print output, accept user input, or perform actions have value even without a return value. You will learn the importance of return in Chapter 12, but not all functions need to return something.
Misconception 4
"Python reads function bodies when it reads the definition."
Python reads the definition and records it, but it does not execute the body until the function is called. This is why a typo or logic error inside a function body does not cause an error when Python reads the definition — it only causes an error when the function is actually called.
Misconception 5
"You should always use a main() function."
The main() convention is a good habit for organized programs, but Python does not require it. Small programs and scripts are often written without a main(). The convention becomes more valuable as programs grow.
Chapter 11 Checklist
Use this to confirm your understanding before moving to Chapter 12
Concepts
  • I can explain what a function is and why functions matter.
  • I can define a function using def, with correct syntax and indentation.
  • I can call a function and explain what happens when Python runs the call.
  • I can explain the difference between defining a function and calling it.
  • I understand that Python reads definitions before running calls, and that a definition must appear before a call that uses it.
  • I can explain the main() convention and why it is a clean way to organize a program.
Skills
  • I can choose clear, specific, verb-based names for functions.
  • I can write functions that print formatted output, such as headers, separators, and footers.
  • I can identify repeated code and rewrite it using a function.
  • I can trace a program that calls multiple functions, including functions that call other functions.
Debugging
  • I can recognize a NameError caused by calling a function before it is defined.
  • I can recognize a missing function call caused by forgotten parentheses.
  • I can identify and correct an IndentationError inside a function body.
  • I understand why code outside a function cannot use variables defined inside that function.
Preview — Chapter 12
Parameters, Arguments, and Return Values

Chapter 11 introduced functions as named blocks of code that you can define and call. The functions in this chapter did one kind of job: they ran some statements and finished.

Real functions need to do more. They need to receive information — a name, a number, a score — and they often need to send a result back to the caller. A function that calculates an average should be able to send that average back to the program that called it.

Chapter 12 covers parameters, arguments, and return values — the tools that make functions genuinely powerful. You will learn how to pass information into a function, how to get results back out, and how to use function results in expressions and in further calculations. You will also study one of the most common beginner confusions in all of Python: the difference between print() and return. Mastering that distinction will make every function you write from Chapter 12 onward more useful and more correct.

MGU Library Connection
  • Programming with Python — Appendix G: Function Design Reference
  • Programming with Python — Appendix D: Common Python Error Messages
  • Companion resource: Function Design Guide
  • Companion resource: Print-versus-Return Guide
  • Next chapter: Parameters, Arguments, and Return Values (Chapter 12)
  • MGU Computer Science Foundations — background reading on algorithms and procedures