Python functions with multiple parameter brackets

I've been having trouble understanding what h(a)(b) means. I'd never seen one of those before yesterday, and I couldn't declare a function this way:

def f (a)(b):
    return a(b)

When I tried to do def f (a, b):, it didn't work either. What do these functions do? How can I declare them? And, finally, what's the difference between f(a, b)and f(a)(b)?


Functions with multiple parameter brackets don't exist, as you saw when you tried to define one. There are, however, functions which return (other) functions:

def func(a):
    def func2(b):
        return a + b
    return func2

Now when you call func() it returns the inner func2 function:

>>> func2 = func(1)  # You don't have to call it func2 here
>>> func2(2)
3

But if you don't need the inner function later on, then there's no need to save it into a variable and you can just call them one after the other:

>>> func(1)(2)   # func(1) returns func2 which is then called with (2)
3

This is a very common idiom when defining decorators that take arguments.


Notice that calling func() always creates a new inner function, even though they're all named func2 inside of the definition of our func:

>>> f1 = func(1)
>>> f2 = func(1)
>>> f1(1), f2(1)
(2, 2)
>>> f1 is f2
False

And, finally, what's the difference between f(a, b)and f(a)(b)?

It should be clear now that you know what f(a)(b) does, but to summarize:

  • f(a, b) calls f with two parameters a and b
  • f(a)(b) calls f with one parameter a, which then returns another function, which is then called with one parameter b

f(a)(b) just means that the expression f(a) returns a value that is itself callable. It's a short form of

g = f(a)
g(b)

You might be more comfortable adding a pair of redundant parentheses to emphasize that this is not a single syntactic construct.

(f(a))(b)  # f(a) is evaluated first, then the result is applied to b

It is exactly analogous to the same doubling of square brackets for indexing nested dictionaries.

d1[x][y]

is equivalent to

d2 = d1[x]
d2[y]

Lets say we have an expression like

f(a)(b)

then, f(a) returns a function itself which gets invoked with argument b. Consider the following example

def f(a):
   def g(b):
      return a * b
   return g

Then f(5)(4) evaluates to 5 * 4, since f(5) returns a function which is basically

def g(b):
   return 5 * b

One could now do stuff like this

mult_by_5 = f(5)
[mult_by_5(x) for x in range(10)]

Let's be fancy, what about more nested functions?:

def f(a):
  def g(b):
    def h(c):
      return a * b *c
    return h
  return g
f(2)(3)(4) # 24