Concepts / Side Effects vs. Return Values

Side Effects vs. Return Values

Void functions perform actions but return None, not a usable value.

  • Programming

The Visible Action Trap

Many learners expect every function call to produce a value that can be stored and reused. That expectation seems reasonable when a call visibly does something. For example, print displays text on the screen. However, the action performed by a function and the value returned to its caller are separate things. A function can perform a visible action while returning no usable value.

What do you think happens?

What do you think result contains after the function call performs its printing action?

  • The text that was printed
  • None
  • The string 'None'
Reveal answer

Answer: None

The printing action happens on the screen, but the function does not provide a usable return value. Python represents that absence with the special value None.

callscausesreturnscallsreturnsCallerVoid functionperforms an actionScreen outputNoneno usable valueFruitful functionreturns a valueUsable value
How does data or control flow differ when a function performs an action versus when it returns a value?

Two Kinds of Function Results

A void function performs an action, often a side effect such as printing, but returns None rather than a usable value. A fruitful function computes and returns a meaningful value that the caller can store and use in later calculations.

Function kindWhat happens when it runsWhat the caller receives
Void functionIt performs an action or side effectNone
Fruitful functionIt computes a resultA meaningful value

The distinction is not whether the function call appears to do something. A void function may clearly change what you see on the screen or perform another action. The distinction is whether the caller receives a meaningful value for storage, calculation, or another operation.

def print_twice(text): print(text) print(text) result = print_twice('Bing') print(result)

Output
Bing
Bing
None

Assignment Stores None

Assignment does not capture everything a function does. It captures the value produced by the function call. In the print_twice example, the two lines of screen output are the side effect. The value assigned to result is None. The sequence is therefore: call the function, observe its action, assign its returned value, and then observe None when the variable is displayed.

assignment evaluates callstores returned valueresultnot assignedprint_twiceprints 'Bing' twiceresultNone
What value is placed in a variable after assigning the result of a function that has no usable return value?

Tracing a Void Function Assignment

Determine what happens when the result of an action-oriented function is assigned to a variable.

Call: The function is called and performs its action by printing the text twice.

Return: The function does not provide a usable value, so Python represents the absence of that value as None.

Assignment: The variable receives the function call's result, so the variable contains None rather than the printed text.

Later use: Displaying the variable shows None. The screen output and the returned value were separate results.

The function performs its action, but the assigned variable contains None.

What None Means

None is a special Python value with its own type, NoneType. It is not merely an empty slot, and it is not the text string 'None'. The two may look similar when displayed, but they represent different things. None signals that a function did not produce a usable value for its caller, while 'None' is text.

ItemMeaningType
NoneA special value representing no usable return valueNoneType
'None'Text containing the characters N, o, n, eString
NoneNoneType'None'string
What is the difference between the special value None and the text string 'None'?

Tracing an Unexpected None

A None-related bug usually begins with an incorrect expectation about the function's result. The caller expects a meaningful value, but the function is void or reaches a path that does not provide one. Trace the call from the caller into the function, identify the action it performs, and then check what value reaches the assignment. If that value is None, the function did not produce the result the caller needs.

entersthen check resultyesnoFunction callFunction actionrunsExpected valueprovided?Meaningful valuecaller can use itNonecaller received no usablevalue
At which point in the function's control flow does the expected value fail to be returned, causing None to reach the caller?
  • Assuming visible output is the function's return value

    Printing is an action or side effect. The function can perform that action and still return None.

    Fix: Trace the value returned by the call separately from what appears on the screen.

  • Using a variable containing None in a calculation

    None is not a usable calculation result.

    Fix: Identify whether the called function is fruitful before using its result in a calculation.

  • Confusing None with the string 'None'

    None has type NoneType, while 'None' is text.

    Fix: Keep the special value None conceptually separate from the string 'None'.

Practice the Distinction

EASY

A function call produces visible output, and its result is assigned to a variable. Explain separately what the function did as an action and what value the variable received. Then classify the function as void or fruitful and explain why.

Hints
  • Do not treat screen output and a returned value as the same result.
  • Ask whether the caller received a meaningful value that can be used later.
  • If the function did not return a usable value, identify the special value Python uses.
MEDIUM

You expected a variable to contain a value for a calculation, but debugging shows that it contains None. What should you inspect first: the screen output, the function's action, or the value returned to the caller? Explain your choice.

Hints
  • The bug concerns the value assigned to the variable.
  • A function can complete an action without returning a usable value.
  • Trace the function call and identify whether it is void or fruitful.

Key Takeaways

  1. A void function performs an action but returns None rather than a usable value.
  2. A fruitful function returns a meaningful value that the caller can store and use.
  3. Assigning the result of a void function stores None in the variable.
  4. None is a real Python value of type NoneType, not the string 'None'.
  5. When an expected value becomes None, trace the function call and check whether the function actually returns a usable result.

Key Takeaways

  • Side effects describe what a function does; return values describe what the caller receives.
  • Void functions return None, even when their actions are visible.
  • Fruitful functions return meaningful values that can be stored and used.
  • None and the string 'None' are different, and None has type NoneType.
  • An unexpected None is a debugging clue that the caller did not receive the value it expected.