In the following example I show some mixins that may or may not use *args
or **kwargs
:
class AMixin():
def __init__(self, **kwargs):
print("AMixin")
self.a = 'a' str(kwargs.get('a', ''))
class BMixin():
def __init__(self, **kwargs):
print("BMixin")
self.b = 'b' str(kwargs.get('b', ''))
class ABMixin(AMixin, BMixin):
def __init__(self, **kwargs):
print("ABMixin")
super().__init__(**kwargs)
class A(AMixin):
def __init__(self, **kwargs):
super().__init__(**kwargs)
class B(BMixin):
def __init__(self, **kwargs):
super().__init__(**kwargs)
class AB(ABMixin):
def __init__(self, **kwargs):
print("AB")
super().__init__(**kwargs)
AB(a='a', b='b')
Here I encounter an issue because the last mixin is calling its parent which doesn't exist:
Cell In [4], line 9, in BMixin.__init__(self, *args, **kwargs)
8 def __init__(self, *args, **kwargs):
----> 9 super().__init__(*args, **kwargs)
10 print("BMixin")
11 self.b = 'b' str(kwargs.get('b', ''))
TypeError: object.__init__() takes exactly one argument
(the instance to initialize)
How should I modify this example to allow any combination of mixins, and inherit mixins in any order?
One possible UGLY solution is to add a dummy end mixin:
class EndMixin:
def __init__(self, **kwargs):
...
class AMixin(EndMixin):
def __init__(self, **kwargs):
print("AMixin")
self.a = 'a' str(kwargs.get('a', ''))
class BMixin(EndMixin):
def __init__(self, **kwargs):
print("BMixin")
self.b = 'b' str(kwargs.get('b', ''))
CodePudding user response:
You can make your mixins inherit from a base-class that stops the super call to object
.
class BaseMixin:
def __init__(self, *args, **kwargs):
pass
class AMixin(BaseMixin):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
print("AMixin")
self.a = 'a' str(kwargs.get('a', ''))
class BMixin(BaseMixin):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
print("BMixin")
self.b = 'b' str(kwargs.get('b', ''))
class ABMixin(AMixin, BMixin):
...
class A(AMixin):
...
class B(BMixin):
...
class AB(ABMixin):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
obj = AB(a='a', b='b')
print(obj.b)
print(obj.a)
CodePudding user response:
It looks like each mix-in should take ownership of the argument it operates on. Declare the parameter explicitly (keyword-only if you like), and leave **kwargs
to handle the keyword arguments your mix-in doesn't know about.
class AMixin:
def __init__(self, *args, a='', **kwargs):
super().__init__(*args, **kwargs)
print("AMixin")
self.a = 'a' str(a)
class BMixin:
def __init__(self, *args, b='', **kwargs):
super().__init__(*args, **kwargs)
print("BMixin")
self.b = 'b' str(b)
class A(AMixin):
pass
class B(BMixin):
pass
class AB(ABMixin):
def __init__(self, **kwargs):
print("AB")
super().__init__(**kwargs)
AB(a='a', b='b')