Concepts / Calling Functions and Using Return Values

Calling Functions and Using Return Values

A function is written like a regular subroutine, with the addition that you must specify the value it returns.

  • Programming
Interactive lab

Try it: Defining and Calling Functions

What def and a call really do: def only creates a function object, a call binds the arguments to the parameters in a new frame and runs the body, return ends the call at once and its value replaces the call expression in the caller — while a function that only prints gives back None.

How it works

  1. def name(params): creates a function object and binds the name to it; the body does not run yet.
  2. A call evaluates its arguments, opens a new frame, binds each parameter to its argument and runs the body from the top.
  3. return value ends the call immediately (lines after it never run) and sends the value back; the frame and its local names are discarded.
  4. In the caller, the call expression is replaced by the returned value, which can be stored, used in a larger expression or passed to another call.
  5. A body that ends without return (e.g. one that only prints) makes the call evaluate to None — so x = f() stores None and None + 1 raises TypeError.
  6. Calling a name before its def has run raises NameError: the function does not exist yet.

Default run (18 steps): The program is ready. Python runs it from the top, one statement at a time. Idea: the value a call returns is what the caller stores. … The program finished. Console: 8.

Simplified: Four fixed, hand-written programs; you edit the literal arguments, switch the body between return and print, and move the def after the calls. The lab's own small evaluator runs them (your input is never executed as code); every variant was run in CPython 3.12 and the lab reproduces its sys.settrace line/call/return/exception events, its output and its error message. Functions are shown as <function name> without a memory address.

Educational simulation

Loading the simulation…

A Function That Hands a Value Back

You have probably already used functions without writing any yourself. Math.sqrt() computes a square root, and TextIO.getInt() reads an integer that the user types. In both cases the function gives your program a value, and the program can then use that value in later work. The natural next question is how to write functions of your own that provide a value in the same way.

The answer is the return statement. A function is written in much the same way as a regular subroutine. Its overall form is the same, with one addition: you must specify the value that the function is to return, and the return statement is the place where that value is specified. This article covers the syntax of the return statement, how to read one, and how to predict what it produces.

Predicting the Result of a Doubling Function

Before reading any further, study the function below. It takes one number, and its return statement names an expression built from that number. Work out what the caller receives before you read on.

java
Output
8
Notes on the code
  • The function receives 4 as its input and names it total inside the function
  • The return statement evaluates total * 2, which is 8
  • The caller stores the returned 8 in result and prints it

What do you think happens?

What does the caller print: 4 or 8?

  • 4

  • 8

Reveal answer
Answer:

8

The return statement hands back the value of its expression, total * 2, not the input. The input is 4, so the expression evaluates to 8, and only that 8 leaves the function. The 4 was never returned.

Anatomy of the Return Statement

The return statement is built from two parts. The keyword return begins the statement. The expression that follows it is the value to be returned. An expression is anything that produces a value, such as a single variable name, a number, or a calculation. In the doubling example, the keyword is return and the expression is total multiplied by 2.

returnkeyword that begins thestatementtotal * 2expression that isevaluated;closes the statement
Which part of the return statement begins it, which part determines the value sent back, and what does the closing semicolon do?

The keyword is the anchor of the statement, and the expression is the part that gets evaluated. The expression determines the result. If you change total * 2 to total + 2, the value returned changes, while the keyword stays exactly the same. The source presents the template with a closing semicolon as part of the notation, so write the semicolon along with the keyword and expression. The part to learn above all is the keyword followed by an expression.

Definition

A return statement has the form return followed by an expression. The expression supplies the value that is handed back to the place where the function was called.

Returning a Value Versus Running a Subroutine

A function and a regular subroutine look alike. Both are written with the same overall form. The one addition for a function is that you must specify the value it returns. A subroutine that only performs actions does not deliver anything back to its caller, so the call is used as a step that does work. A function delivers a value, so the call is used as something that produces a result the program can use.

FeatureRegular subroutineFunction with return
Overall formWritten in the usual subroutine formSame form, with a value specified
Return statementNot required for delivering a valueRequired: return followed by an expression
What comes back to the callerNothing is handed back as a valueThe value of the return expression
How the call is usedAs a step that performs an actionAs a value that can be stored, printed, or used in further calculation

Subroutine versus function with a return value

Following Control and Value Back to the Caller

When the caller reaches doubleIt(4), execution moves into the function. The function evaluates its return expression, and then the call is finished. Control returns to the caller at the point where the call was made, and the returned value takes the place of the call in the calling statement. The diagram below shows the order of these interactions.

Calling codeint result = doubleIt(4)doubleItreturn total * 2call with 4return 8
After the call runs, where does execution go next, and which line in the caller resumes?

The return statement is the last thing the function does with its value. Once the expression has been evaluated and handed back, the call is over. Notice that the value does not travel as the original input. What travels back is the result of evaluating the expression.

4argument passed intotal * 2evaluated inside doubleIt8value handed backresultassigned in the callerbound to totalevaluatedassigned
How does the value produced by the return expression travel out of the function and get used in the assignment in the caller?

Evaluating a Return Expression Step by Step

Worked example

Predicting the value of a call

Given the function doubleIt with return total * 2, what value does the statement int result = doubleIt(4) store in result?

  1. 1
    Identify the input

    The call passes 4, so inside the function the name total refers to 4.

  2. 2
    Evaluate the expression

    The return expression total * 2 becomes 4 * 2, which produces 8.

  3. 3
    Hand back the result

    Only the evaluated value 8 leaves the function. The input 4 does not leave the function.

  4. 4
    Complete the assignment

    The call is replaced by 8, so result receives 8.

Result

result holds 8

Mistakes When Reading Return Statements

  • Common mistake

    Assuming the function returns its input

    What it looks like

    Reading doubleIt(4) as producing 4 because 4 was passed in.

    Why it fails

    The return statement hands back the value of its expression, not the input. The expression total * 2 is evaluated first, and only its result leaves the function.

    Do this instead

    Evaluate the return expression with the actual input to get the returned value, here 8.

  • Common mistake

    Treating the keyword as the value

    What it looks like

    Expecting return itself to supply a number.

    Why it fails

    The keyword return begins the statement. The value comes from the expression that follows it.

    Do this instead

    Look at the expression after return to find what is handed back.

  • Common mistake

    Changing the keyword when the result is wrong

    What it looks like

    Rewriting return as another word while leaving the expression alone.

    Why it fails

    The expression determines the result. Changing total * 2 to total + 2 changes the returned value, while the keyword stays the same.

    Do this instead

    Inspect and correct the expression that feeds the return statement.

  • Common mistake

    Forgetting that the call is finished once the return statement runs

Tracing a Wrong Result to Its Source

When a program prints an unexpected number, follow the chain in this order: first the call, then the expression in the return statement, and finally the value that appears where the call was made. This order matches the way the value is produced and then delivered. Checking the return statement and the expression that feeds it is the first step when a result is unexpected.

Practice Predicting Return Values

EASY

Suppose a function is declared as public static int tripleIt(int total) with the body return total * 3; and a caller runs int answer = tripleIt(5);. Without running the code, predict the value stored in answer. Then name the single line that is responsible for that value.

Hints
  • Identify the input first. The call passes 5, so total refers to 5 inside the function.
  • Evaluate the return expression total * 3 with total equal to 5.
  • The line responsible for the value is the return statement, because its expression determines what is handed back.

Key Takeaways

  • A function is written like a regular subroutine, with the addition that you must specify the value it returns through a return statement.
  • A return statement has the form return followed by an expression. The keyword begins the statement, and the expression supplies the value handed back.
  • The returned value is the result of evaluating the expression, not the input passed to the function.
  • When a result is unexpected, check the return statement and the expression feeding it first, then follow the value back to the call.