Functions are blocks of code designed to do one specific job. Instead of writing the same logic five times, you write it once inside a function and call it whenever you need it.
Defining and Calling Functions
You define a function using the def keyword.
# Defining a function
def show_welcome():
print("Welcome back!")
print("Loading dashboard...")
# "Calling" it to run the code inside:
show_welcome()
Parameters vs. Arguments
- Parameters: The placeholders you define in the function (the “variables” in the parentheses).
- Arguments: The actual data you pass into the function when you call it.
# 'name' is the parameter
def greet(name):
print(f"Hello, {name}")
# "Alice" is the argument
greet("Alice")
Positional vs. Keyword Arguments
By default, Python matches arguments to parameters based on their position (order). However, you can also use keywords to be explicit.
def describe_pet(name, animal_type):
print(f"I have a {animal_type} named {name}.")
# Positional: Order matters!
describe_pet("Hamster", "Rex") # Output: I have a Rex named Hamster. (Wait, what?)
# Keyword: Order doesn't matter.
describe_pet(animal_type="Hamster", name="Rex") # Output: I have a Hamster named Rex.
Default Values
You can provide default values for parameters. If the user doesn’t provide an argument, Python uses the default.
def make_coffee(size="Medium"):
print(f"Making a {size} coffee.")
make_coffee("Large") # Making a Large coffee.
make_coffee() # Making a Medium coffee.
Returning Values
If you want a function to give data back to the rest of your program, you use return.
Once a function hits a return statement, it exits immediately. Any code below that return line is ignored.
def add(a, b):
return a + b
print("This will never run")
result = add(5, 10)
print(result) # 15
Every function in Python returns something. If you don’t write a return statement, the function automatically returns None.
def boring_function():
x = 1 + 1
result = boring_function()
print(result) # Output: None
Local vs. Global Scope
A variable created in the main body of your script (outside of any function) is “Global.” These variables can be read by any function in your file.
# This is a Global variable
user_name = "Daniel"
def say_hello():
# We can read the global variable inside here
print(f"Hello, {user_name}")
say_hello() # Output: Hello, Daniel
Variables created inside a function are Local. They only exist inside that function. Once the function finishes, those variables are destroyed.
def my_func():
secret = "I only exist here"
return secret
print(secret) # NameError: name 'secret' is not defined
If you want to use a value from a function, you must return it and save it to a new variable outside.
def calculate_tax(amount):
total = amount * 1.2
return total
# We save the returned 'total' into a new variable called 'bill'
bill = calculate_tax(100)
print(bill) # 120.0
The “Read-Only” Trap
By default, Python treats global variables inside a function as read-only. If you try to change a global variable inside a function, Python will actually create a new local variable with the same name instead of updating the global one.
score = 0 # Global
def update_score():
score = 100 # Python thinks this is a NEW local variable
print(f"Local score: {score}")
update_score() # Local score: 100
print(f"Global score: {score}") # Global score: 0 (It didn't change!)
For now, don’t try to change global variables inside functions. Instead, pass the value as an argument, change it, and return the new result. This is called keeping your functions “pure.”
Guard Clauses
Instead of nesting if statements inside functions, use the “Early Return” style. It makes your code much cleaner.
# MUDDY CODE
def check_age(age):
if age >= 18:
# Do a lot of logic here...
return "Allowed"
else:
return "Denied"
# CLEAN CODE (Guard Clause)
def check_age(age):
if age < 18:
return "Denied" # Exit early
# Do a lot of logic here...
return "Allowed"
pass keyword
Python doesn’t allow empty code blocks. If you start an if statement or define a def function but don’t put any code inside yet, your program will crash with an IndentationError.
The pass statement acts as a null operation (it tells Python to “do nothing” so you can keep your code running while you build other parts.).
# A placeholder function
def calculate_rocket_trajectory():
pass # Come back to this once I have the math
is_emergency = True
if is_emergency:
# TODO: Add siren sounds and flashing lights
pass
else:
print("All clear.")
# Python skips the 'pass' and continues the script.
print("System scan complete.")
Docstrings
A Docstring is a literal string used to document a specific segment of code. Unlike a regular comment (#), a docstring describes what the function does and is actually stored as part of the function’s metadata.
Why use them?
- Readability: They help others understand your logic without reading every line of code.
- Tooling: Many Code Editors (like VS Code) will show this text in a pop-up when you hover over the function name.
- Automation: Tools can automatically generate official documentation websites based on these strings.
The Syntax
Docstrings are placed immediately after the function header and are wrapped in triple double-quotes """.
def calculate_area(radius):
"""
Calculates the area of a circle given its radius.
Args:
radius (float): The distance from the center to the edge.
Returns:
float: The total area of the circle.
"""
import math
return math.pi * (radius ** 2)
# Now, if you hover over 'calculate_area' in your editor,
# you'll see the explanation above.
Accessing Docstrings via Code
Because docstrings are stored in the function object, you can actually print them out while your program is running using the __doc__ attribute:
print(calculate_area.__doc__)
While you can write anything inside a docstring, most Python developers follow a specific format (like the Google Style used in the example above). This keeps your documentation consistent as your projects grow larger.