As a data engineer, writing modular code is essential. You aren't just writing scripts that run from top to bottom; you are building reusable, type-safe, and fault-tolerant pipelines. At the heart of clean, maintainable Python code lies the humble function.
In this article, we’ll explore the anatomy of Python functions, how type annotations work, and why distinguishing between pure and impure functions matters for building reliable ETL (Extract, Transform, Load) pipelines.
- The Anatomy of a Function: Parameters vs. Arguments A function is a unit of code defined within a greater code structure that works on inputs and produces a concrete output.
Parameters: The variables defined in the function signature.
Arguments: The actual values passed to the function when it is called.
Let's look at a recursive function to calculate powers, complete with pre-conditions (requires) and post-conditions (returns):
In the definition above, b is the parameter, and the value passed to it during execution is the argument.
- Type Annotations and Why They Matter By default, Python's compiler or interpreter can often infer data types automatically. However, there are times when you want to explicitly declare types—especially to catch errors early or simplify debugging complex pipeline code.
Important Rule: When you write type annotations in Python function definitions, parentheses around the parameters are mandatory.
Here is the same power function explicitly annotated with types:
Why use explicit type annotations?
Clarity: It acts as living documentation for anyone reading your data pipeline modules.
Debugging: If the compiler throws an obscure type error, explicit annotations help isolate the mismatch instantly.
Type Safety: Ensures your data transformations (e.g., Pandas DataFrames or SQL inputs) receive expected data types.
- Pure vs. Impure Functions in Data Pipelines Pure Functions A pure function is one where the return value depends solely on the arguments passed to it, and it produces no side effects (it does not modify external variables or state).
Advantage: If called multiple times with the same arguments, the compiler or system only needs to evaluate it once, making caching and optimization seamless.
Example (GCD calculation):
Impure Functions & Side Effects
An impure function interacts with the outside world or modifies variables outside its local scope (e.g., modifying global states, reading system time via Date(), or generating random numbers via random()).
Here, inc() has a side effect because it mutates the external variable y, meaning the same input will yield different results depending on external state.
Checklist for Data Engineers
Modular Design: Break repetitive bulk statements into reusable subroutines (functions).
Type Safety: Use type annotations (param: type) when clarity and debugging precision are needed.
Side-Effect Management: Keep your core data transformation logic inside pure functions to ensure predictable, bug-free pipelines.




Top comments (0)