What I like most about nested functions is that it is less verbose than classes. The equivalent class definition to your maker function is:
class clsmaker(object):
def __init__(self, N):
self.N = N
def __call__(self, X):
return X * self.N
That doesn't seem so bad until you start adding more arguments to the constructor. Then doing it the class way takes an extra line for each argument, while the function just gets the extra args.
It turns out that there is a speed advantage to the nested functions as well:
>>> 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
This may be due to there being fewer opcodes involved in the nested functions version:
>>> 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