This decorator wraps the class's __init__ function to check that provided set of methods is present on the instantiated class. This is useful for avoiding inheritance in mix-in classes. We can inherit directly from object and still make it clear what methods we expect in other classes to be combined with the mix-in.
Requires at least Python 2.6, which added class decorators.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | def require_methods(*method_args):
"""Class decorator to require methods on a subclass.
Example usage
------------
@require_methods('m1', 'm2')
class C(object):
'This class cannot be instantiated unless the subclass defines m1() and m2().'
def __init__(self):
pass
"""
def fn(cls):
orig_init = cls.__init__
def init_wrapper(self, *args, **kwargs):
for method in method_args:
if (not (method in dir(self))) or \
(not callable(getattr(self, method))):
raise Exception("Required method %s not implemented" % method)
orig_init(self, *args, **kwargs)
cls.__init__ = init_wrapper
return cls
return fn
|
Avoiding inheritance makes mix-in classes much more compose-able. One way to do this is to have each mix-in inherit from object and declare any methods they expect to be present in the concrete class.
For more context, see the presentation linked at http://blog.genforma.com/2011/05/27/talk-on-python-mix-in-classes/