Funciones de Python con múltiples paréntesis de parámetros

He estado teniendo problemas para entender lo que significa h(a)(b) . Nunca había visto uno de esos antes de ayer, y no podía declarar una función de esta manera:

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

Cuando intenté hacer def f (a, b): tampoco funcionó. ¿Qué hacen estas funciones? ¿Cómo puedo declararlos? Y, finalmente, ¿cuál es la diferencia entre f(a, b) y f(a)(b) ?

Las funciones con paréntesis de parámetros múltiples no existen, como se vio cuando intentó definir uno. Hay, sin embargo, funciones que devuelven (otras) funciones:

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

Ahora, cuando llama a func() , devuelve la función func2 interna:

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

Pero si no necesita la función interna más adelante, entonces no hay necesidad de guardarla en una variable y puede llamarlas una tras otra:

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

Este es un lenguaje muy común al definir decoradores que toman argumentos.


Tenga en cuenta que llamar a func() siempre crea una nueva función interna, aunque todos se denominan func2 dentro de la definición de nuestra func :

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

Y, finalmente, ¿cuál es la diferencia entre f(a, b) y f(a)(b) ?

Debe quedar claro ahora que sabe lo que hace f(a)(b) , pero para resumir:

  • f(a, b) llama a f con dos parámetros a y b
  • f(a)(b) llama a f con un parámetro a , que luego devuelve otra función, a la que luego se llama con un parámetro b

f(a)(b) simplemente significa que la expresión f(a) devuelve un valor que es a su vez llamable. Es una forma corta de

 g = f(a) g(b) 

Podría sentirse más cómodo al agregar un par de paréntesis redundantes para enfatizar que esto no es una construcción sintáctica única.

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

Es exactamente análogo a la misma duplicación de corchetes para la indexación de diccionarios nesteds.

 d1[x][y] 

es equivalente a

 d2 = d1[x] d2[y] 

Digamos que tenemos una expresión como

 f(a)(b) 

entonces, f(a) devuelve una función que se invoca con el argumento b . Considera el siguiente ejemplo

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

Entonces f(5)(4) evalúa como 5 * 4 , ya que f(5) devuelve una función que es básicamente

 def g(b): return 5 * b 

Ahora se podría hacer cosas como esta

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

Seamos lujosos, ¿qué pasa con las funciones más anidadas ?:

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