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

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

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.