Functional Programming: Beginner
Databricks processes petabytes of data daily using functional patterns where map() applies the same transformation to millions of records simultaneously, and filter() removes unwanted rows without a single for loop. The data engineering teams at companies like Instacart use these tools to clean and reshape raw data and to validate it, in pipelines that run thousands of times per day. lambda functions let you define a transformation inline without naming it, so pipeline code stays compact. This lesson covers map() and filter() first and then lambda; most data transformation pipelines are built from those patterns.
Calling a function
Every time you write print("Hello") or len("text"), you're calling a function. These are built-in functions that come with Python, created by Python developers to handle common tasks. The print() function displays output to the screen. The len() function calculates the length of a string or collection. You do not need to know how these functions work internally; you just need to know what to give them and what they give back.
Each function call follows the same pattern: write the function name, open parentheses, provide any data the function needs (called arguments), and close parentheses. The function processes the arguments and may produce a result you can use.
Functions for your own rules
To create a function, use the def keyword (short for "define") followed by the function name with parentheses after it, and end the line with a colon. The lines of code that belong to the function must be indented. This indented block is called the function body, and it contains the code that runs when you call the function.
Notice the order of output. The code inside the function only runs when you call it with greet(). You can call a function as many times as you want, and each call executes the function body from the beginning.
Parts of a function definition
Function naming conventions
- calculate_area
- format_user_name
- validate_email
- convert_temperature
- get_total_price
- doStuff
- f
- myFunction
- process
- x
Indentation is mandatory
When you call greet("Alice"), Python assigns the value "Alice" to the parameter name. Inside the function, name behaves like any other variable, holding that value for the duration of the function call.
Multiple parameters
Default parameter values
The parameter greeting has a default value of "Hello". When you call greet("Alice") with only one argument, greeting uses its default. When you provide a second argument, that value overrides the default.
A formatting function with defaults
Wrong number of arguments
Functions can send data back to the caller using the return statement. This is how a function hands a result back for the caller to store or pass on to another function.
The return statement immediately exits the function and sends the specified value back to where the function was called. That value replaces the function call in the expression, as if you had written the value directly.
Return versus print
print() and return get confused because both look like output, but only one of them hands the calling code a value it can use:
- Displays text on screen
- For human consumption only
- Function returns None
- Can't use the value later
- Side effect, not a result
- Sends value back to caller
- For program consumption
- Value can be stored and used
- Enables further calculations
- Actual function result
add_with_print displays 8 on the screen but returns None, so result1 is useless. add_with_return does not display anything but returns 8, which we can store and reuse in later calculations.
Functions without a return
If a function doesn't have a return statement, or if return is used without a value, the function automatically returns None. None is Python's special value representing "nothing" or "no value."
Return exits immediately
When Python encounters a return statement, it immediately exits the function. Any code after the return statement never runs. This is useful for early exits when you have already determined the result:
- Local scope - variables created inside a function, only visible there
- Global scope - variables created outside all functions, visible everywhere
- A variable's scope is determined by where it is created
Local variables
Global variables
Parameters as local variables
The parameter x inside the function is a separate variable that happens to start with the same value as number. Changing x does not change number. This is called pass by value for simple types like numbers and strings.
Scope lookup order
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:
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).
int: Whole numbers like 5, -10, 0float: Decimal numbers like 3.14, -2.5str: Text strings like "hello"bool: Boolean values True or FalseNone: The special "no value" valuelist: A list of itemsdict: 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:
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
- 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
Mistakes that come up with functions
Forgetting to call the function
- def greet():
- print("Hello!")
- # Function defined but never called
- # Nothing prints!
- def greet():
- print("Hello!")
- greet() # Call with parentheses
- # Prints "Hello!"
Forgetting the return statement
- def add(a, b):
- result = a + b
- # Forgot return!
- total = add(3, 5) # total is None
- def add(a, b):
- return a + b
- total = add(3, 5) # total is 8
Calling before defining
Confusing a reference with a call
greet (without parentheses) is the function object itself. greet() (with parentheses) calls the function. They are very different:
> You are a data analyst at Salesforce building a reusable ETL utility that cleans contact records across ten regional CSV files, each requiring the same standardization logic applied consistently without duplicating code.
def packages the record-cleaning logic once with a descriptive name so every regional file calls the same standardization routine without copy-pasting.return passes the cleaned record list back to the caller so the result can be written to the output file or passed to the next pipeline stage.def to define functions that package reusable codeparam=value) make parameters optionalreturn sends a value back; without it, the function returns Noneglobal keywordBuilding reusable blocks of logic
- Category
- Python
- Difficulty
- beginner
- Duration
- 37 minutes
- Challenges
- 17 hands-on challenges
Topics covered: Defining Functions, Function Parameters, Return Values, Scope and Variables, Type Hints and Documentation
Lesson Sections
- Defining Functions (concepts: Functions)
A function is a named block of code you can run from anywhere in a program, so the same logic never has to be written twice. Calling a function Functions for your own rules Built-in functions cover common operations, but your programs have unique requirements. You might need to calculate taxes for your specific business rules, format names according to your company standards, or validate data in ways Python can't predict. Creating your own functions lets you package this custom logic and reuse i
- Function Parameters (concepts: Flexible Arguments)
Most functions need input: an area function needs the dimensions, and a name formatter needs the name. Parameters are variables that receive values when you call the function. They appear inside the parentheses in the function definition and act as placeholders for the actual values you will provide. Parameters and arguments get mixed up a lot. They describe the same value, seen once from the definition and once from the call. Multiple parameters Functions can accept multiple parameters, separat
- Return Values (concepts: Functions)
Return versus print Functions without a return Functions without return values exist for their "side effects", such as printing messages or writing to files. Return a value when the caller needs one back; leave it out when the action itself is the function's job. Return exits immediately Each condition checks the age and returns as soon as one matches, so the function never runs more code than it needs to.
- Scope and Variables (concepts: Scope)
Scope determines where a variable exists and can be accessed. Understanding scope prevents bugs where variables unexpectedly have wrong values or do not exist when you expect them to. Python has 2 main scopes relevant to functions: local scope (inside a function) and global scope (outside all functions). Local variables Variables created inside a function are local to that function. They're created when the function starts running and destroyed when the function finishes. They don't exist outsid
- Type Hints and Documentation (concepts: 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 Type hints are not enforced Type hints pay off in larger codebases The payoff grows with the size of the codebase and the number of people working in it. Write type hints from the start, so the habit is already in place when the codeb