Academy
ProgrammingPython IntermediateFunctions — Advanced

Functions — Advanced

Functions That Accept Any Number of Arguments

Sometimes you don't know in advance how many arguments a function will receive. Python's print() itself is an example — you can pass it one argument or ten, and it handles all of them.

You can write functions that do the same using *args.

The * before numbers tells Python: collect all positional arguments into a tuple called numbers. Whether you pass two or twenty, they all arrive in that one tuple.

The name args in *args is just convention — *numbers, *values, *items all work the same way. The * is what matters.

Keyword Arguments With **kwargs

Similarly, **kwargs collects any number of keyword arguments into a dictionary.

The ** tells Python: collect all keyword arguments into a dictionary called details. The caller can pass any keys they like. The function receives them all.

Combining Both

You can use *args and **kwargs together. Positional arguments must come first:

level is a normal required parameter. *messages collects any extra positional arguments. **metadata collects any keyword arguments. Each plays a different role.

Functions as Values

In Python, functions are values — just like integers and strings. You can store them in variables, put them in lists, and pass them to other functions.

style is a parameter that receives a function. style(message) calls whatever function was passed in. This is called a higher-order function — a function that takes another function as an argument.

This pattern is more powerful than it first appears. Instead of writing if/else chains to switch between behaviours, you pass the behaviour itself as data.

Sorting With a Key Function

The built-in sorted() function accepts a key argument — a function that tells Python what to sort by.

key=len means: for each name, call len() on it, and sort by that value. Python calls your key function once per item and sorts by the results.

Lambda — One-Line Functions

Writing a separate named function just to extract a dictionary value feels heavy. Python gives you lambda for exactly this situation — a function defined in a single expression.

lambda parameters: expression

lambda p: p["price"] defines an anonymous function that takes one argument p and returns p["price"]. No def, no name, no return keyword — just the expression.

Lambda functions are not a replacement for regular functions. Use them for short, throwaway logic — especially as arguments to sorted(), map(), and filter(). If the logic needs a name or is more than one expression, write a proper function.

map() and filter()

Two built-in higher-order functions worth knowing:

  • map(function, iterable) — applies a function to every item and returns the results
  • filter(function, iterable) — keeps only items where the function returns True

Both return lazy iterators, so wrap them in list() to see the results immediately.

You'll notice these do exactly what list comprehensions do. In Python, comprehensions are generally preferred for readability:

# These are equivalent:
discounted = list(map(lambda p: p * 0.9, prices))
discounted = [p * 0.9 for p in prices]

map and filter exist and appear in real code — especially older Python codebases — so you should recognise them. But for new code, comprehensions are the more Pythonic choice.

What You Have Learned

Functions in Python are more flexible and powerful than they first appear.

The key ideas:

  • *args collects any number of positional arguments into a tuple
  • **kwargs collects any number of keyword arguments into a dictionary
  • Functions are values — they can be stored in variables and passed as arguments
  • Higher-order functions accept other functions as parameters
  • sorted() takes a key function that defines what to sort by
  • lambda parameters: expression defines a small anonymous function inline
  • map() applies a function to every item; filter() keeps items where the function returns True

In the next lesson, you'll learn about scope in depth — how Python decides which variable a name refers to, and how closures allow functions to remember values from their surrounding context.