I have a hierarchy of classes with a whole bunch of similar methods that I've managed to factor out the common parts of using a closure and a decorator:
def makemethod(kernel_method, output_class):
def closure(self, start, end):
set().up()
common()
stuff()
result = []
for i in range(start, end):
args = more().standard().stuff()
result.append(kernel_method(self, args))
finish().up()
return output_class(result)
return closure
def mymethod(output_class):
def decorator(kernel_method):
return makemethod(kernel_method, output_class)
return decorator
Each method that follows the pattern, whether it's a method defined in the base class or a derived class, just has to define its "kernel" and use the decorator to wrap it in the common code:
@mymethod(Class1)
def a_method_that_builds_a_Class1(self, args):
# just the kernel!
@mymethod(Class2)
def a_method_that_builds_a_Class2(self, args):
# just the kernel!
@mymethod(Class2)
def a_different_way_to_build_a_Class2(self, args):
# just the kernel!
All of this works beautifully and does exactly what I want it to. The only problem is, to make it work I've had to define the makemethod
function and its decorator wrapper outside of my base class, as module-level functions, and that seems awfully weird to me (though maybe in Python it's not weird at all?)
The inner function closure
makes absolutely no sense except as a method of my class (the "common stuff" it does uses all kinds of class attributes), so the outer function that it's defined inside should be a class member, right? But if I try to make the outer functions static or class methods of my base class, I can use them to decorate methods of derived classes, but I can't call them in the base class itself, because inside a class's definition its own name isn't in scope yet. And my base class does have methods that need decorating.
I suppose I could put the closure and decorator in a class on their own, and have my "base" class inherit from that class. Is that what I should do, or is it stylistically okay in Python for closure/decorator "templates" for methods to be module-level functions?