python factory functions compared to class

2020-02-03 13:19发布

问题:

Just working through learning python and started to look at nested/factory functions (simple example):

def maker(N):
    def action(X):
        return X * N
    return action

Are there any advantages of factory functions over creating a class? performance? memory? clean up?

回答1:

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  


回答2:

Comparing a function factory to a class is comparing apples and oranges. Use a class if you have a cohesive collection of data and functions, together called an object. Use a function factory if you need a function, and want to parameterize its creation.

Your choice of the two techniques should depend on the meaning of the code.



回答3:

Nesting functions allows one to create custom functions on the fly.

Have a look at e.g. decorators. The resulting functions depend on variables that are bound at creation time and do not need to be changed afterwards. So using a class for this purpose would make less sense.