return Statement
Python's return statement returns a value from a function to the caller. Multiple values can be returned together using a tuple, and writing return in the middle of a function achieves early exit (guard clauses). Omitting return or writing it alone returns None. Return type hints (-> type) can also be used to declare the return type.
Syntax
# Return a value
def function_name(arg) -> return_type:
return value
# Return multiple values as a tuple
def function_name(arg) -> tuple:
return value1, value2, value3
# Explicitly return None
def function_name(arg) -> None:
return # or: return None
# Early return (guard clause)
def function_name(arg):
if invalid_condition:
return # exit here
# main processing
return value
Keywords and Syntax
| Syntax | Notes |
|---|---|
| return value | Returns the value to the caller and exits the function. |
| return value1, value2 | Returns multiple values as a tuple using comma separation. Can be unpacked on the receiving side. |
| return | Returns None and exits the function when no value is specified. |
| return None | Explicitly returns None. Same behavior as return alone. |
| def f() -> type_name: | Declares the return type with a type hint. Not enforced at runtime; used for documentation and static analysis tools. |
| def f() -> None: | Explicitly indicates that the function has no return value. |
| def f() -> tuple[int, str]: | Specifies the element types of the returned tuple (Python 3.9+). |
Sample Code
Basic usage of return. Compare the case where a value is returned against the case where it is omitted.
basic_return.py
# Function that returns a judgment based on a PSYCHO-PASS crime coefficient.
def get_judgment(crime_coefficient):
if crime_coefficient >= 300:
return "Lethal Eliminator"
elif crime_coefficient >= 100:
return "Paralyzer"
else:
return "Normal"
print(get_judgment(299)) # Paralyzer
print(get_judgment(300)) # Lethal Eliminator
print(get_judgment(50)) # Normal
# When return is omitted, None is returned.
def log_scan(name):
print(name + "'s hue scanned")
# No return, so None is returned.
result = log_scan("Tsunemori Akane")
print("Return value:", result) # None is displayed.
python3 basic_return.py Paralyzer Lethal Eliminator Normal Tsunemori Akane's hue scanned Return value: None
Returning multiple values together. Writing them comma-separated returns a tuple that can be unpacked on the receiving side.
multiple_return.py
# Function that returns multiple pieces of enforcer information.
def get_enforcer_info(name):
# Comma-separated values form a tuple.
if name == "Kogami Shinya":
return name, 1, "Enforcer"
elif name == "Ginoza Nobuchika":
return name, 2, "Inspector"
else:
return name, 0, "Unknown"
# Receive as a tuple.
info = get_enforcer_info("Kogami Shinya")
print(info) # ('Kogami Shinya', 1, 'Enforcer')
print(type(info)) # <class 'tuple'>
# Unpack into individual variables.
name, number, role = get_enforcer_info("Ginoza Nobuchika")
print(name + " / Number: " + str(number) + " / Role: " + role)
# Use _ to discard unused values.
name, _, role = get_enforcer_info("Tsunemori Akane")
print(name + " role: " + role)
python3 multiple_return.py
('Kogami Shinya', 1, 'Enforcer')
<class 'tuple'>
Ginoza Nobuchika / Number: 2 / Role: Inspector
Tsunemori Akane role: Unknown
Guard clauses using early return. Checking and rejecting invalid input at the top of the function keeps the main logic from being deeply nested.
guard_clause.py
# Function that validates input before constructing a message.
# Guard clauses reject invalid input up front.
def format_crime_coefficient(name, coefficient):
# Guard 1: return early if name is empty
if not name:
return "Error: name is not set"
# Guard 2: return early if coefficient is negative
if coefficient < 0:
return "Error: invalid coefficient"
# Main logic runs only after passing the guards.
return name + " crime coefficient: " + str(coefficient)
print(format_crime_coefficient("Makishima Shogo", 0))
print(format_crime_coefficient("", 150))
print(format_crime_coefficient("Kagari Shusei", -1))
print(format_crime_coefficient("Saiga Jouji", 88))
python3 guard_clause.py Makishima Shogo crime coefficient: 0 Error: name is not set Error: invalid coefficient Saiga Jouji crime coefficient: 88
Explicit None return and return type hints (-> type).
type_hint_return.py
# Type hints declare the return type.
# They are not enforced at runtime; they are for documentation and static analysis.
# -> str: declares that a string is returned.
def get_dominator_mode(coefficient: int) -> str:
if coefficient >= 300:
return "Lethal Eliminator"
elif coefficient >= 100:
return "Paralyzer"
return "Standby Mode"
# -> None: declares that nothing is returned (returns None).
def log_dominator_use(user: str, mode: str) -> None:
print("[Dominator log] " + user + " / mode: " + mode)
return None # return None and return have the same behavior.
# -> tuple[str, int]: specifies element types in the tuple (Python 3.9+).
def scan_psycho_pass(name: str) -> tuple[str, int]:
data = {
"Tsunemori Akane": 10,
"Kogami Shinya": 108,
"Makishima Shogo": 0,
}
coefficient = data.get(name, 50)
return name, coefficient
mode = get_dominator_mode(250)
print(mode)
log_dominator_use("Ginoza Nobuchika", mode)
target, coeff = scan_psycho_pass("Kogami Shinya")
print(target + " / coefficient: " + str(coeff))
print(get_dominator_mode(coeff))
python3 type_hint_return.py Paralyzer [Dominator log] Ginoza Nobuchika / mode: Paralyzer Kogami Shinya / coefficient: 108 Paralyzer
Common Mistakes
Common Mistake 1: Forgetting return causes None to be returned
When a function that is supposed to return a value is missing a return statement, Python implicitly returns None. The caller expecting a return value then gets an error.
ng_missing_return.py
# Wrong: return is missing in one branch
def get_dominator_mode(coefficient):
if coefficient >= 300:
return "Lethal Eliminator"
elif coefficient >= 100:
return "Paralyzer"
# The else branch has no return -> None is returned
mode = get_dominator_mode(50)
print(mode) # None (not intended)
print("Mode: " + mode) # TypeError: can only concatenate str (not "NoneType") to str
python3 ng_missing_return.py
None
Traceback (most recent call last):
File "ng_missing_return.py", line 10, in <module>
print("Mode: " + mode)
TypeError: can only concatenate str (not "NoneType") to str
ok_complete_return.py
def get_dominator_mode(coefficient):
if coefficient >= 300:
return "Lethal Eliminator"
elif coefficient >= 100:
return "Paralyzer"
return "Standby Mode" # Write return in every branch.
mode = get_dominator_mode(50)
print("Mode: " + mode) # Standby Mode
python3 ok_complete_return.py Mode: Standby Mode
Common Mistake 2: Code after return is never executed
When return executes, the function ends at that point. Any code written after return is never executed (unreachable code).
ng_dead_code.py
def scan_psycho_pass(name):
print(name + " scanning...")
return "Scan complete"
print("Post-scan processing") # Wrong: this is after return, so it never runs
result = scan_psycho_pass("Tsunemori Akane")
print(result)
python3 ng_dead_code.py Tsunemori Akane scanning... Scan complete
For post-processing, write it before return or use try/finally.
ok_code_order.py
def scan_psycho_pass(name):
print(name + " scanning...")
result = "Scan complete"
print("Post-scan processing (before return)") # Write before return.
return result
output = scan_psycho_pass("Kogami Shinya")
print(output)
python3 ok_code_order.py Kogami Shinya scanning... Post-scan processing (before return) Scan complete
Common Mistake 3: return behaves differently inside a generator
In a regular function, return value returns the value. But in a generator function (one that contains yield), return does not return a value to the caller — it raises StopIteration to end the generator. Use yield to produce values from a generator.
ng_generator_return.py
# Wrong: trying to return a value from a generator with return
def scan_targets(names):
for name in names:
yield name + " scanning"
return "Scan complete" # This becomes the value of StopIteration, not a normal return
targets = ["Tsunemori Akane", "Kogami Shinya", "Makishima Shogo"]
for result in scan_targets(targets):
print(result)
# "Scan complete" is not printed
python3 ng_generator_return.py Tsunemori Akane scanning Kogami Shinya scanning Makishima Shogo scanning
ok_generator_yield.py
# Use yield to emit a completion message as well.
def scan_targets(names):
for name in names:
yield name + " scanning"
yield "Scan complete" # yield emits the value to the caller
targets = ["Tsunemori Akane", "Kogami Shinya", "Makishima Shogo"]
for result in scan_targets(targets):
print(result)
python3 ok_generator_yield.py Tsunemori Akane scanning Kogami Shinya scanning Makishima Shogo scanning Scan complete
Notes
A return statement can appear anywhere in a function. The function terminates immediately at the first return reached, and no code after it executes. Using this property for guard clauses lets you reject invalid input or boundary conditions at the top of the function, keeping the main logic from becoming deeply nested.
The comma-separated syntax for returning multiple values is effectively returning a tuple. Unpacking on the receiving side lets you assign the values to individual variables. Unused return values are conventionally discarded with _. For a related feature that lazily generates multiple values, see yield (generators).
The -> type type hint is available from Python 3.5 onward. It does not enforce the type at runtime, so returning an incorrect type raises no error. Type checking is performed by static analysis tools such as mypy. Explicitly writing -> None when there is no return value improves readability. For a deeper look at type hints, also see isinstance() / type().
If you find any errors or copyright issues, please contact us.