Skip to content

Higher Order Functions#

A higher-order function (HOF) takes functions as arguments and/or returns functions. Python treats functions as first-class values — HOFs are idiomatic, not academic.

How to use this page

Pair with Lambda Functions, Partial Functions, Map, Filter and Reduce.

At a glance
Track Python Advanced → Advanced Functions
Sections 6 major topics
Outline Use the right-hand TOC to jump

Topics: First-class functions · Functions as arguments · Functions as return values · Composition · Callbacks and strategy pattern · HOF vs OOP

  1. First-class functions
  2. Functions as arguments
  3. Functions as return values
  4. Composition
  5. Callbacks and strategy pattern
  6. HOF vs OOP

First-class functions#

def greet():
    return "Hello"

say = greet           # assign
call = lambda f: f()  # pass
result = call(greet)  # invoke via variable

Functions are objects with identity, attributes, and methods.


Functions as arguments#

def apply(fn, value):
    return fn(value)

apply(abs, -5)          # 5
apply(lambda x: x * 2, 10)  # 20

def run_twice(fn, arg):
    fn(arg)
    fn(arg)

Built-in HOFs#

Function Purpose
sorted(it, key=fn) Sort by key function
max(it, key=fn) Maximum by key
map(fn, it) Transform (lazy iterator)
filter(fn, it) Filter (lazy iterator)
any / all Short-circuit predicates
sorted(words, key=len)
sorted(words, key=str.lower)
max(students, key=lambda s: s.score)

Functions as return values#

def make_validator(min_val: int, max_val: int):
    def validate(x: int) -> bool:
        return min_val <= x <= max_val
    return validate

is_percent = make_validator(0, 100)
is_percent(50)   # True

Factory pattern — see Closures.


Composition#

Combine small functions into pipelines:

def compose(f, g):
    return lambda x: f(g(x))

double = lambda x: x * 2
inc = lambda x: x + 1
double_then_inc = compose(inc, double)
double_then_inc(3)   # 7

# Manual pipeline
def pipeline(x, *fns):
    for fn in fns:
        x = fn(x)
    return x

Modern alternative: explicit steps or comprehensions when pipeline is short.


Callbacks and strategy pattern#

def process_items(items, on_item, on_error=None):
    for item in items:
        try:
            on_item(item)
        except Exception as e:
            if on_error:
                on_error(item, e)
            else:
                raise

process_items([1, 2, 0], on_item=lambda x: print(10 / x))

HOF replaces subclassing for simple strategy selection.


HOF vs OOP#

HOF Class with methods
Lightweight Structured state
Functional style Inheritance
Great for single callback Many related behaviors

Interviews: either works — prefer clarity.


Interview traps (quick reference)#

Trap What goes wrong Safe approach
Side effects in key= Sort mutates or logs unexpectedly Pure key functions
map in Py3 Returns iterator — use once list(map(...)) or comprehension
Over-abstraction Unreadable one-liners Name intermediate functions
Late binding in loop callbacks Wrong captured variable Factory or default arg

Mental model checklist#

  1. What makes a function "higher-order"?
  2. How is sorted(key=...) a HOF?
  3. When is returning a function better than a class?
  4. What is function composition?

What's next#

Topic Page
Lambdas Lambda Functions
Partial Partial Functions
Map/filter/reduce Map, Filter and Reduce
Closures Closures