Type Hints and Documentation
Concepts covered: Type Hints
On a codebase that several people work on, you need to record what types of values each function expects and returns. Python's type hints are annotations for exactly that. They don't change how code runs; they're documentation for humans and tools.
Basic type hints
Add type hints after parameter names with a colon and the type. Add return type hints after the closing parenthesis with -> followed by the type:
def calculate_area(width: float, height: float) -> float:
return width * height
def greet(name: str) -> str:
return "Hello, " + name + "!"
def is_adult(age: int) -> bool:
return age >= 18
def print_message(message: str) -> None:
print(message)These hints tell readers that calculate_area expects 2 float numbers and returns a float. greet expects a str and returns a str. is_adult expects an int and returns a bool (True or False).
Common type hints
- int: Whole numbers like 5, -10, 0
- float: Decimal numbers like 3.14, -2.5
- str: Text strings like "hello"
- bool: Boolean values True or False
- None: The special "no value" value
- list: A list of items
- dict: A dictionary of key-value pairs
Type hints are not enforced
Python doesn't enforce type hints at runtime. You can pass a str where the hint says int, and Python will try to run the code. This differs from statically-typed languages like Java or TypeScript. Type hints are purely informational:
def double(x: int) -> int:
return x * 2
print(double(5))
print(double("ab"))
Output:
10 abab
The type hint says int, but Python happily multiplies a str by 2 (which repeats it). Type hints are for documentation and for external tools like type checkers (mypy) that analyze code before you run it.
Type hints pay off in larger codebases
The payoff grows with the size of the codebase and the number of people working in it.
Benefits of type hints
- Documentation: Readers immediately know expected types
- IDE support: Code editors provide better autocomplete
- Error prevention: Type checkers catch bugs before runtime
- Refactoring: Easier to change code with type information
- Team communication: Clear contracts between functions
Write type hints from the start, so the habit is already in place when the codebase grows.
Outside the language itself, a lot of tooling has grown up around type hints.
Mistakes that come up with functions
These show up in everyone's code at some point, and each is quick to fix once you recognize it:
Forgetting to call the function
Defining a function doesn't run it. You must call the function with parentheses to execute its code:
- Wrong
- def greet():
- print("Hello!")
- # Function defined but never called
- # Nothing prints!
- Correct
- def greet():
- print("Hello!")
- greet() # Call with parentheses
- # Prints "Hello!"
Forgetting the return statement
If you want to use a function's result, you must return it. Calculating a value without returning it means the result is lost:
- Wrong
- def add(a, b):
- result = a + b
- # Forgot return!
- total = add(3, 5) # total is None
- Correct
- def add(a, b):
- return a + b
- total = add(3, 5) # total is 8
Forgetting return is a very common bug. Try fixing the one below, where a function calculates a value and then loses it.
Calling before defining
Python executes code from top to bottom. A function must be defined before the line that calls it:
# greet() # NameError
def greet():
print("Hello!")
greet()Confusing a reference with a call
greet (without parentheses) is the function object itself. greet() (with parentheses) calls the function. They are very different:
def greet():
return "Hello!"
print(greet)
print(greet())Output:
<function greet at 0x...> Hello!
About this lesson
This section is part of the Functional Programming: Beginner lesson on DataDriven, the home of data engineering. Lessons cover SQL, Python, Spark, data modeling and pipeline architecture, and each section pairs its explanation with worked examples and practice you run as you go.