python – correct way to use super (argument passing)
python – correct way to use super (argument passing)
Sometimes two classes may have some parameter names in common. In that case, you cant pop the key-value pairs off of **kwargs
or remove them from *args
. Instead, you can define a Base
class which unlike object
, absorbs/ignores arguments:
class Base(object):
def __init__(self, *args, **kwargs): pass
class A(Base):
def __init__(self, *args, **kwargs):
print A
super(A, self).__init__(*args, **kwargs)
class B(Base):
def __init__(self, *args, **kwargs):
print B
super(B, self).__init__(*args, **kwargs)
class C(A):
def __init__(self, arg, *args, **kwargs):
print C,arg=,arg
super(C, self).__init__(arg, *args, **kwargs)
class D(B):
def __init__(self, arg, *args, **kwargs):
print D, arg=,arg
super(D, self).__init__(arg, *args, **kwargs)
class E(C,D):
def __init__(self, arg, *args, **kwargs):
print E, arg=,arg
super(E, self).__init__(arg, *args, **kwargs)
print MRO:, [x.__name__ for x in E.__mro__]
E(10)
yields
MRO: [E, C, A, D, B, Base, object]
E arg= 10
C arg= 10
A
D arg= 10
B
Note that for this to work, Base
must be the penultimate class in the MRO.
If youre going to have a lot of inheritence (thats the case here) I suggest you to pass all parameters using **kwargs
, and then pop
them right after you use them (unless you need them in upper classes).
class First(object):
def __init__(self, *args, **kwargs):
self.first_arg = kwargs.pop(first_arg)
super(First, self).__init__(*args, **kwargs)
class Second(First):
def __init__(self, *args, **kwargs):
self.second_arg = kwargs.pop(second_arg)
super(Second, self).__init__(*args, **kwargs)
class Third(Second):
def __init__(self, *args, **kwargs):
self.third_arg = kwargs.pop(third_arg)
super(Third, self).__init__(*args, **kwargs)
This is the simplest way to solve those kind of problems.
third = Third(first_arg=1, second_arg=2, third_arg=3)
python – correct way to use super (argument passing)
As explained in Pythons super() considered super, one way is to have class eat the arguments it requires, and pass the rest on. Thus, when the call-chain reaches object
, all arguments have been eaten, and object.__init__
will be called without arguments (as it expects). So your code should look like this:
class A(object):
def __init__(self, *args, **kwargs):
print A
super(A, self).__init__(*args, **kwargs)
class B(object):
def __init__(self, *args, **kwargs):
print B
super(B, self).__init__(*args, **kwargs)
class C(A):
def __init__(self, arg, *args, **kwargs):
print C,arg=,arg
super(C, self).__init__(*args, **kwargs)
class D(B):
def __init__(self, arg, *args, **kwargs):
print D, arg=,arg
super(D, self).__init__(*args, **kwargs)
class E(C,D):
def __init__(self, arg, *args, **kwargs):
print E, arg=,arg
super(E, self).__init__(*args, **kwargs)
print MRO:, [x.__name__ for x in E.__mro__]
E(10, 20, 30)