Python
method-parameters
function-passing
programming
code-duplication

How do I pass a method as a parameter in Python

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

In Python, functions are first-class objects — they can be assigned to variables, stored in data structures, and passed as arguments to other functions. To pass a function as a parameter, simply use its name without parentheses. Parentheses call the function; without them, you pass the function object itself. This is the foundation for callbacks, higher-order functions, decorators, and strategy patterns in Python.

Basic Example

python
1def greet(name):
2    return f"Hello, {name}!"
3
4def shout(name):
5    return f"HEY {name.upper()}!"
6
7# Pass function as argument — no parentheses
8def apply_greeting(func, name):
9    return func(name)
10
11print(apply_greeting(greet, "Alice"))  # "Hello, Alice!"
12print(apply_greeting(shout, "Alice"))  # "HEY ALICE!"

greet (no parentheses) is the function object. greet("Alice") calls the function and passes the return value.

Function References vs Function Calls

python
1def add(a, b):
2    return a + b
3
4# This is the function OBJECT
5print(add)          # <function add at 0x...>
6print(type(add))    # <class 'function'>
7
8# This CALLS the function and returns the result
9print(add(2, 3))    # 5
10
11# Common mistake:
12def apply(func, a, b):
13    return func(a, b)
14
15# CORRECT — pass the function object
16result = apply(add, 2, 3)  # 5
17
18# WRONG — passes the return value (5), not the function
19# result = apply(add(2, 3), 2, 3)  # TypeError: 'int' object is not callable

Passing Built-In Functions

python
1numbers = [3, 1, 4, 1, 5, 9, 2, 6]
2
3# sorted() accepts a key function
4print(sorted(numbers))                    # [1, 1, 2, 3, 4, 5, 6, 9]
5print(sorted(numbers, key=abs))           # Same (all positive)
6
7# Using built-in functions as arguments
8words = ["banana", "apple", "cherry"]
9print(sorted(words, key=len))             # ['apple', 'banana', 'cherry']
10print(sorted(words, key=str.upper))       # ['apple', 'banana', 'cherry']
11
12# map() takes a function and applies it to each element
13print(list(map(str.upper, words)))        # ['BANANA', 'APPLE', 'CHERRY']
14print(list(map(len, words)))              # [6, 5, 6]
15
16# filter() takes a function that returns True/False
17print(list(filter(str.isalpha, ["abc", "123", "def"])))  # ['abc', 'def']

Passing Lambda Functions

python
1# Lambda — anonymous inline function
2numbers = [3, -1, 4, -1, 5, -9, 2, -6]
3
4# Sort by absolute value
5print(sorted(numbers, key=lambda x: abs(x)))
6# [-1, -1, 2, 3, 4, 5, -6, -9]
7
8# Filter positive numbers
9positives = list(filter(lambda x: x > 0, numbers))
10print(positives)  # [3, 4, 5, 2]
11
12# Pass lambda to a custom function
13def apply_twice(func, value):
14    return func(func(value))
15
16print(apply_twice(lambda x: x + 3, 7))   # 13 (7+3=10, 10+3=13)
17print(apply_twice(lambda x: x * 2, 5))   # 20 (5*2=10, 10*2=20)

Passing Methods (Bound and Unbound)

python
1class Calculator:
2    def __init__(self, base):
3        self.base = base
4
5    def add(self, x):
6        return self.base + x
7
8    def multiply(self, x):
9        return self.base * x
10
11calc = Calculator(10)
12
13# Bound method — includes the instance (self)
14print(calc.add)       # <bound method Calculator.add of <Calculator object>>
15print(calc.add(5))    # 15
16
17# Pass bound method as argument
18def apply_operation(func, value):
19    return func(value)
20
21print(apply_operation(calc.add, 5))       # 15
22print(apply_operation(calc.multiply, 3))  # 30
23
24# Unbound method — the class method itself
25print(Calculator.add)  # <function Calculator.add at 0x...>
26print(Calculator.add(calc, 5))  # 15 — must pass instance explicitly

Callback Pattern

python
1def fetch_data(url, on_success, on_error):
2    try:
3        # Simulate fetching
4        if "invalid" in url:
5            raise ValueError("Bad URL")
6        data = f"Data from {url}"
7        on_success(data)
8    except Exception as e:
9        on_error(e)
10
11def handle_success(data):
12    print(f"Success: {data}")
13
14def handle_error(error):
15    print(f"Error: {error}")
16
17fetch_data("https://api.example.com", handle_success, handle_error)
18# Success: Data from https://api.example.com
19
20fetch_data("https://invalid.com", handle_success, handle_error)
21# Error: Bad URL

Higher-Order Functions

A higher-order function takes a function as input or returns a function as output:

python
1# Returns a function
2def make_multiplier(factor):
3    def multiply(x):
4        return x * factor
5    return multiply
6
7double = make_multiplier(2)
8triple = make_multiplier(3)
9
10print(double(5))   # 10
11print(triple(5))   # 15
12
13# Compose two functions
14def compose(f, g):
15    return lambda x: f(g(x))
16
17add_one = lambda x: x + 1
18square = lambda x: x ** 2
19
20square_then_add = compose(add_one, square)
21print(square_then_add(5))  # 26 (5²=25, 25+1=26)
22
23add_then_square = compose(square, add_one)
24print(add_then_square(5))  # 36 (5+1=6, 6²=36)

Type Hints for Function Parameters

python
1from typing import Callable
2
3def apply(func: Callable[[int, int], int], a: int, b: int) -> int:
4    return func(a, b)
5
6# Callable[[arg_types], return_type]
7def process(
8    items: list[str],
9    transform: Callable[[str], str],
10    predicate: Callable[[str], bool]
11) -> list[str]:
12    return [transform(item) for item in items if predicate(item)]
13
14result = process(
15    ["hello", "hi", "hey", "world"],
16    transform=str.upper,
17    predicate=lambda s: len(s) > 2
18)
19print(result)  # ['HELLO', 'HEY', 'WORLD']

Common Pitfalls

  • Calling the function instead of passing it: apply(greet("Alice")) calls greet immediately and passes the return value. Use apply(greet) to pass the function object. The distinction is parentheses: func is the object, func() is a call.
  • Lambda limitations: Lambdas can only contain a single expression, not statements. You cannot use if/else blocks, assignments, or print in a lambda. For complex logic, define a named function with def.
  • Mutating default arguments in passed functions: If a function parameter has a mutable default (like def f(lst=[])), the default is shared across all calls. This is a Python gotcha unrelated to passing functions but often surfaces in callback patterns.
  • Losing self context with unbound methods: Passing Calculator.add instead of calc.add loses the instance reference. The unbound method requires self as the first argument. Use bound methods (instance.method) for callbacks that need instance state.
  • Not using functools.partial for pre-filling arguments: If you need to pass a function with some arguments pre-filled, use functools.partial instead of wrapping in a lambda: partial(add, 5) instead of lambda x: add(5, x).

Summary

  • Pass functions by name without parentheses: func not func()
  • Built-in functions (len, str.upper, abs) can be passed directly to sorted, map, filter
  • Use lambda for short anonymous functions
  • Bound methods (obj.method) carry the instance; unbound methods (Class.method) do not
  • Use Callable[[arg_types], return_type] for type hints on function parameters
  • Use functools.partial to pre-fill arguments on passed functions

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.