Concepts / Fruitful Functions vs. Void Functions

Fruitful Functions vs. Void Functions

The return statement sends a value from inside a function back to the calling code, making that value the result of the function call.

  • 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 Result Needs a Route Out

A function can compute a result internally, but the calling code needs a way to receive that result. The return statement provides that route. It sends a value from inside the function back to the code that called it, making the value the result of the entire function call.

Following the Returned Value

Consider a function named addtwo that receives two parameters. Inside the function, a local variable named added stores the sum of those parameters. The return statement sends added back to the calling code. When the calling code uses addtwo with 3 and 5, the function computes 8. That 8 becomes the result of the function call, and the calling code can store it in a variable named x.

3 and 5function inputsaddtwocomputes a sumadded88returned valuex8callcomputereturnassign
How does a computed value move from inside a function through the return statement to the variable that receives the function call's result?
Worked example

Tracing addtwo

Determine what value is stored in x after the calling code uses addtwo with 3 and 5.

  1. 1
    Receive inputs

    The function receives 3 and 5 as its two parameter values.

  2. 2
    Compute locally

    The local variable added stores the sum of the parameters, which is 8.

  3. 3
    Return

    The return statement sends the value 8 out of the function.

  4. 4
    Capture the result

    The complete function call produces 8, and the calling code assigns that result to x.

Result

x stores 8. The calling code receives the returned value, not the internal variable named added.

Return Ends Execution

A return statement does two jobs at once. It sends a value back to the caller, and it immediately ends the function. Any code placed after that return statement inside the same function will not run. This behavior is intentional, not an error.

What do you think happens?

A function receives 15. It checks whether the value is greater than 10. If it is, the function returns twice the value, and a print action appears later in the function. Does the print action run?

  • Yes, before the returned value is produced

  • Yes, after the returned value is produced

  • No, because return ends the function immediately

Reveal answer
Answer:

No, because return ends the function immediately.

With 15, the condition is true, so returning 30 ends the function before the later print action can run. With 5, the condition is false, the conditional block is skipped, the print action runs, and then returning 5 ends the function.

Best practice

When tracing a function, stop reading its body as soon as you reach the return statement that executes. Then follow the returned value back to the calling expression.

Local Names and Calling Scope

Variables created inside a function are local to that function. They exist while the function is running and cease to exist once the function returns. The calling code can access the value that was returned, but it cannot access the internal variables used to calculate that value.

calculate_areafunction scopearea2020returned resultcalling codecalling scoperesult20createsreturnstorescreates
What contains the function's local variable, and what contains the separate variable in the calling code that captures the returned value?
Worked example

The area variable does not escape

A function named calculate_area creates a local variable named area with the value 20 and returns that value. The calling code stores the result in result. What can the calling code access?

  1. 1
    Inside the function

    area exists inside calculate_area and holds 20 while the function is running.

  2. 2
    At return

    The function sends the value 20 back to the calling code.

  3. 3
    After return

    area ceases to exist because it was local to the function.

  4. 4
    In the caller

    The calling code stores the returned value in result, so result contains 20.

Result

The calling code can use result, but it cannot use area. Trying to print area in the calling code produces a NameError because area was never defined in that scope.

Two Kinds of Function Results

A fruitful function returns a value that the calling code can assign, print, use in an expression, or pass to another function. The returned value can be a number, string, list, dictionary, or another object, depending on what the function computes.

A void function only performs actions and does not communicate a usable result back to the code that called it. The distinction is about what the caller receives: a fruitful function delivers a value, while a void function performs an action without delivering a result for the caller to use.

Fruitful functionreturns a valuecomputed valuecaller can use itVoid functionperforms an actionno usable resultcaller cannot access acomputed resultdeliversdoes not deliver
What is the difference between a function call that produces a value and one that performs an action without producing a usable result?
FeatureFruitful functionVoid function
Main behaviorComputes and returns a valuePerforms an action without communicating a usable result
What the caller receivesA value that can be assigned, printed, used, or passed onwardNo usable computed result
Role of returnDelivers the function's outputThe function does not deliver a result back to the caller

The key difference is whether the function communicates a usable result to its caller.

Mistakes in Return Tracing

  • Common mistake

    Treating a local variable as though it remains available after the function returns

    What it looks like

    A function calculates a value in area, returns 20, and the calling code then tries to use area.

    Why it fails

    area was created inside the function and ceases to exist when the function returns.

    Do this instead

    Use the variable in the calling scope that captured the returned value, such as result.

  • Common mistake

    Reading code after an executing return statement as though it will run

    What it looks like

    A function returns 30 when its input is 15, but a print action appears after that return.

    Why it fails

    return immediately terminates the function.

    Do this instead

    Stop the trace at the return and do not include later actions in the output.

  • Common mistake

    Confusing the local computation with the function call's result

    What it looks like

    The local variable added stores 8, and the calling variable x also stores 8.

    Why it fails

    The names are different and belong to different scopes, even though the returned value is copied into the caller's variable.

    Do this instead

    Trace the value separately from the variable name: added produces the value, return sends it, and x receives it.

Practice the Trace

MEDIUM

A function receives the value 5. It checks whether the value is greater than 10. If the condition is true, it returns twice the value. Otherwise, it performs a print action and then returns the original value. Predict which value the function returns and whether the print action runs.

Hints
  • First decide whether 5 is greater than 10.
  • If the condition is false, follow the path after the conditional block.
  • The function still returns a value after the print action.

The correct trace is: 5 is not greater than 10, so the conditional return is skipped. The print action runs, and then the function returns 5. This contrasts with the input 15, where the function returns 30 immediately and the later print action never runs.

Essential Takeaways

  1. 1
    The return statement sends a value from inside a function back to the calling code.
  2. 2
    The returned value becomes the result of the complete function call and can be assigned to a variable in the calling scope.
  3. 3
    Executing return ends the function immediately, so later code inside that function does not run.
  4. 4
    Local variables exist only while their function is running; after return, the caller can access the returned value but not those local variables.
  5. 5
    A fruitful function delivers a usable result, while a void function performs an action without delivering a usable result.

At a glance

  • Return moves a computed value from a function to its calling code.
  • A function call's result can be stored in a variable, printed, used in an expression, or passed to another function.
  • Return stops the function immediately.
  • Local variables disappear when the function returns, while the caller retains the returned value in its own variable.
  • Fruitful functions return usable values; void functions perform actions without communicating a usable result.

Related concepts

More concepts starting with F