Explain Codes LogoExplain Codes Logo

Passing functions with arguments to another function in Python?

python
functions
lambda
partial-functions
Anton ShumikhinbyAnton Shumikhin·Mar 2, 2025
TLDR

To elegantly pass functions with prepared arguments, employ lambda or functools.partial. Lambda crafts anonymous functions instantly while functools.partial pre-stocks function arguments. Here's a nifty example with both techniques:

Lambda usage:

def add(a, b): return a + b result = (lambda x: add(x, 3))(2) # Result is 5, math is fun!

Functools.partial usage:

from functools import partial def add(a, b): return a + b prepped_add = partial(add, 2) # add() now comes with 2! result = prepped_add(3) # Result is 5

Choose lambda for brevity or functools.partial for clarity with pre-decided arguments.

Dynamic function calls with *args

In case of a dynamic number of arguments, the *args parameter comes as a blessing in Python. The star (*) denotes a variable number of arguments. It is popularly written as *args.

Function Execution Pipeline

Defining a function executor makes our pipeline neat:

def perform(func, *args): return func(*args) # Taste it with result = perform(add, 5, 5) # Result is 10, Twice of 5, Woohoo!

This perform function is a magician showing how *args work with an array of arguments.

Looping execution with list comprehension

For those moments when you need a function call for a list in motions:

actions = [partial(add, n) for n in range(5)] # Prep the add() function with digits 0 to 4 results = [action(10) for action in actions] # The 'add to 10' club

List comprehension works amazingly well with functools.partial—like peanut butter and jelly!

The charms of callable objects

Custom callable classes - Object-Oriented Style

class Addinator: def __init__(self, n): self.n = n def __call__(self, x): return self.n + x add_to_3 = Addinator(3) result = add_to_3(2) # Result is 5, classy!

This pattern holds a state and it could boost cleaner code in convoluted scenarios.

Fun with lambda - one-liners on-the-fly

result = (lambda x, y: x + y)(2, 3) # Result is 5, they're still in love!

Lambda makes life less elaborate and jollier with on-spot definitions.

Fun visualisation

Imagine, the chef (👨‍🍳) is you and your recipes are functions. Each extraordinary dish (🍲) needs explicit ingredients (arguments).

Recipe (Function): Soup making 🍲 Ingredients (Args): Water (💧), Vegetables (🥦), and a pinch of Salt (🧂)

Behold, you have an assistant (👩‍🍳) who needs to prepare the ingredients before the magic happens.

def prepare_ingredients(💧, 🥦, 🧂): # The assistant gets everything ready for the gala return (💧, 🥦, 🧂)

When all are ready, it's time to cook!

def cooking_show(prepare, cook): ingredients = prepare() dish = cook(*ingredients) return dish

Voila...! Here's the masterpiece!

👩‍🍳 Prepares: (💧, 🥦, 🧂) 👨‍🍳 Cooks: 🍲

Ready to rock: A mouth watering soup made from functions with arguments!

Make your way around common Gotchas

All Lambdas are superheroes, not supervillains!

Making lambdas complex can lead to confusing code:

action = (lambda x, _: x + [4])([1, 2, 3], "unnecessary") # This lambda had too much coffee today

Don't let lambdas turn into supervillains. Use them as the superheroes they are.

Friendly naming for partial functions

Named partial functions make your codes approachable:

add_four = partial(add, 4) # add() now always comes with 4! result = add_four(16) # Adds 4 to input, returning 20.

Descriptive names for partial functions are like clean clothes, it makes it easier to identify them in public.

Function calls without the wrapper

While wrappers are cool, some days, it's best to let functions just breathe:

compute = map(add_four, range(5)) # Applies add_four on 0, 1, 2, 3, 4. Let them enjoy the fresh air!

This is like going organic, pure, and to the point with your tools.