I have some classes whose methods which I want to be able to add to other classes on optionally. My initial solution was to use mixins, but this can get a bit ugly:
class Schedule(Enumerator, Humanizer, Inferer, ...):
...
So I thought hey, perhaps I could use class decorators to achieve the same effect.
@enumerator
@humanizer
@inferer
class Schedule(object):
...
And here is a sample of the decorator functions:
import inspect
def inferer(original_class):
from myproj.lib.inferer import Inferer
methods = inspect.getmembers(Inferer, predicate=inspect.ismethod)
for method in methods:
setattr(original_class, method[0], types.MethodTypes(method[1], original_class))
return original_class
...which seems to add the methods and classmethods appropriately to decorated classes. However, when I call one of these added methods (or classmethods) on the decorated class, I get some errors.
For methods:
>>> Schedule().humanize()
TypeError: unbound method humanize() must be called with Humanizer instance as first argument (got type instance instead)
...which seems to indicate these are added as classmethods?
For classmethods:
>>> schedule = Schedule.infer(foo)
TypeError: infer() takes exactly 2 arguments (3 given)
Note the definition of infer:
class Inferer(object):
@classmethod
def infer(cls, dates):
...
I added some lines to infer to show what arguments it's getting when called as Schedule.infer():
cls: <class 'myproj.lib.inferer.Inferer'>
dates: <class 'myproj.Schedule'>
So, my question:
What is going wrong in the decorator function to cause these added methods and classmethods to behave strangely? Or, better put, how to I modify the decorator function to handle these additions properly?
Please let me know if I can provide any clarification on any point.