Lo que más me gusta de las funciones anidadas es que es menos detallado que las clases. La definición de clase equivalente a la función de su fabricante es:
class clsmaker(object):
def __init__(self, N):
self.N = N
def __call__(self, X):
return X * self.N
que no parece tan malo hasta que comienza a añadir más argumentos al constructor. Luego hacerlo de la forma de clase toma una línea adicional para cada argumento, mientras que la función simplemente obtiene los argumentos adicionales.
Resulta que hay una ventaja de velocidad a las funciones anidadas así:
>>> T1 = timeit.Timer('maker(3)(4)', 'from __main__ import maker')
>>> T1.timeit()
1.2818338871002197
>>> T2 = timeit.Timer('clsmaker(3)(4)', 'from __main__ import clsmaker')
>>> T2.timeit()
2.2137160301208496
Esto puede ser debido a que hay un menor número de códigos de operación implicados en la versión funciones anidadas:
>>> dis(clsmaker.__call__)
5 0 LOAD_FAST 1 (X)
3 LOAD_FAST 0 (self)
6 LOAD_ATTR 0 (N)
9 BINARY_MULTIPLY
10 RETURN_VALUE
>>> act = maker(3)
>>> dis(act)
3 0 LOAD_FAST 0 (X)
3 LOAD_DEREF 0 (N)
6 BINARY_MULTIPLY
7 RETURN_VALUE
que es una diferencia de tiempo significativa..resultados interesantes – meade