inheritance - How to mixin behavior using class decorators in Python? -


i have base class has lot of direct sub classes. there multiple independent features shared multiple of sub classes. use case python's cooperative inheritance. however, features should wrap behavior outside, need earlier in method resolution order.

class wrappedsub(featurea, featureb, featurec, realsub):      def __init__(self, *args, **kwargs):         featurea.__init__(foo=42)         featureb.__init__(bar=13)         featurec.__init__(foobar=546)         realsub.__init__(*args, **kwargs)  class realsub(base):     # lots of code ... 

it nice decorate child classes instead.

@mixin(featurea, 42) @mixin(featureb, 13) @mixin(featurec, 546) class realsub(base):     # lots of code ... 

precisely, need @mixin decorator first block below equivalent second.

@mixin(sub, *feature_args, **feature_kwargs) class realsub:     # lots of code ...  class realsub:     # lots of code ... class wrappedsub(feature, realsub):     def __init__(self, *sub_args, **sub_kwargs):         feature.__init__(self, *feature_args, **feature_kwargs)         realsub.__init__(self, *sub_args, **sub_kwargs) realsub = wrappedsub 

how possible in python 3?

you can use python's cooperative multiple-inheritance system write mixin classes, rather trying implement them class decorators. how i've understood term "mixin" used in python oop.

class base:     def method(self, param):         value = param + 18         return value  class featureone:               # inherit base      def method(self, param):         if param == 42:             return 13         else:             return super().method(param)   # call next class in inheritance chain  class child(featureone, base):     def method(self, param):         value = super().method(param)         value *= 2         return value 

this isn't quite same wanted, since calls featureone class's method implementation between base , child classes' versions, rather before child thing. instead add new grandchild class inherits features care first, , child last, if can't adjust methods work in order (the grandchild class's body empty).

if want use decorators flip order around, think make work, decorator building "grandchild" class (though doesn't know normal inheritance hierarchy). here's rough attempt @ mixin decorator works want:

def mixin(*mixin_classes, **mixin_kwargs): # decorator factory function     def decorator(cls): # decorator function         class wrapper(*mixin_classes, cls):             def __init__(self, *args, **kwargs):                 wrapped_kwargs = mixin_kwargs.copy() # use passed kwargs update                 wrapped_kwargs.update(kwargs)        # mixin args, caller can override                 super().__init__(*args, **wrapped_kwargs)         # maybe modify wrapper's __name__, __qualname__, __doc__, etc. match cls here?         return wrapper     return decorator 

the mixin classes should call super().__init__(*args, **kwargs) own __init__ method (if have one), can accept (and not pass on) keyword-only arguments of own want passed mixin decorator:

class featureone:     def __init__(self, *args, foo, **kwargs): # note foo keyword-only argument         self.foo = foo         super().__init__(*args, **kwargs)      def method(self, param):         if param == self.foo:             return 13         else:             return super().__method__(param)  @mixin(featureone, foo=42) class child(base):     def method(self, param):         return super().method(param) * 2 

the decorator should work either mixin classes passed 1 decorator call (e.g. @mixin(featurea, featureb, featurec, foo=42, bar=13, foobar=546)), or several nested decorator calls. mro of final class same either way.


Comments

Popular posts from this blog

javascript - Slick Slider width recalculation -

jsf - PrimeFaces Datatable - What is f:facet actually doing? -

angular2 services - Angular 2 RC 4 Http post not firing -