Lesson 25 of 30 · Programming Fundamentals
Functions and Data Structures
With variables, types, and control flow in hand, the next step is learning how to organize code and data. Functions let you package a piece of logic so it can be reused and reasoned about on its own. Data structures let you group related values so a program can manage many things at once instead of juggling dozens of separate variables. Together they are the building blocks of every nontrivial program.
Functions
A function is a named block of code that takes some inputs, does work, and optionally hands back a result. You define one with def, list its parameters in parentheses, and use return to send a value back to the caller. The values you pass in when calling are the arguments.
def mean(numbers):
"""Return the arithmetic mean of a non-empty list of numbers."""
return sum(numbers) / len(numbers)
result = mean([2, 4, 9]) # arguments: the list [2, 4, 9]
print(result) # 5.0
Here numbers is the parameter; [2, 4, 9] is the argument bound to it when the function runs. The triple-quoted string just below def is a docstring — a short description of what the function does. Tools and the built-in help() read docstrings, so they double as documentation.
Parameters can have default argument values, used when the caller omits them:
def celsius_to_fahrenheit(celsius, round_to=1):
"""Convert a Celsius temperature to Fahrenheit."""
return round(celsius * 9 / 5 + 32, round_to)
print(celsius_to_fahrenheit(100)) # 212.0
print(celsius_to_fahrenheit(36.6, 2)) # 97.88
Why bother wrapping logic in functions? They enable reuse (write the conversion once, call it anywhere), abstraction (callers think about what it does, not how), and testability (a function with clear inputs and outputs is easy to check in isolation). Crucially, they let you avoid copy-pasting the same logic in five places — where a later fix would have to be made five times. Defining functions with def and capturing their result with return are core parts of the language 1.
Core data structures
Python provides four everyday containers. Choosing the right one makes code clearer and faster.
A list is an ordered, mutable sequence — use it for collections that grow, shrink, or change. Items are reached by index, starting at 0:
temps = [12.0, 15.5, 9.8]
temps.append(18.2) # lists can change
print(temps[0]) # 12.0
A tuple is an ordered but immutable sequence. Because it can’t change, it’s a good fit for fixed records or coordinates. A handy feature is unpacking several values at once:
point = (3, 4)
x, y = point # unpacking
print(x, y) # 3 4
A dict (dictionary) maps keys to values and offers fast lookup by key — ideal when you want to find data by a label rather than a position:
ages = {"ana": 30, "ben": 25}
print(ages["ana"]) # 30
A set holds unordered, unique elements. It’s the right choice for membership tests and removing duplicates:
seen = {"a", "b", "a"}
print(seen) # {'a', 'b'} — duplicate dropped
print("b" in seen) # True
As a rule of thumb: reach for a list when order matters and contents change, a tuple for fixed groupings, a dict when you look things up by key, and a set for uniqueness or fast membership checks.
Iterating and comprehensions
A for loop walks through any of these containers. Over a list you get each item; over a dict, .items() yields key/value pairs you can unpack directly:
for temp in temps:
print(temp)
ages = {"ana": 30, "ben": 25}
for name, age in ages.items():
print(name, age)
When you want to build a new list by transforming an existing one, a list comprehension is more concise and readable than a loop with append:
xs = [1, 2, 3, 4]
squares = [x ** 2 for x in xs] # [1, 4, 9, 16]
Read it left to right: “the value x ** 2 for each x in xs.” The container protocols and comprehension syntax shown here are standard Python 1.
Worked example: combining both
The real payoff comes when functions and data structures work together. The function below takes a list of numbers and returns a dict of summary statistics — a single, labeled result the caller can index by name:
def summarize(numbers):
"""Return min, max, and mean of a non-empty list as a dict."""
return {
"count": len(numbers),
"min": min(numbers),
"max": max(numbers),
"mean": sum(numbers) / len(numbers),
}
stats = summarize([12.0, 15.5, 9.8, 18.2])
print(stats["mean"]) # 13.875
print(stats["max"]) # 18.2
The list carries the input data, the function encapsulates the computation, and the dict gives the output meaningful names. That separation — data in structures, behavior in functions — scales from these few lines to programs of any size.
References
- The Python Tutorial and Language Reference (Python 3). Python Software Foundation. verified Cited at: The Python Tutorial.