The code is quite self-explanatory. I want to call both class A
and class B
__init__
methods.
Code:
class A(object):
def __init__(self, name):
self.name = name
class B(object):
def __init__(self, age):
self.age = age
class C(A, B):
def __init__(self, name, age):
A.__init__(self, name)
B.__init__(self, age)
def display(self):
print(self.name, self.age)
c = C("xyz", 12)
c.display()
Output:
xyz 12
I want to use super()
instead of explicitly stating
A.__init__(self, name)
B.__init__(self, age)
I am unable to find any resource for the same, need help.
The following does not work:
class A(object):
def __init__(self, name):
super(A, self).__init__()
self.name = name
class B(object):
def __init__(self, age):
super(B, self).__init__()
self.age = age
class C(A, B):
def __init__(self, name, age):
# A.__init__(self, name)
# B.__init__(self, age)
super(C, self).__init__(name, age)
def display(self):
print(self.name, self.age)
c = C("xyz", 12)
c.display()
CodePudding user response:
When you create an instance of C
, it's better if you pass keyword arguments so that you know which is which. Positional arguments work too but with keyword arguments, you don't have to worry about messing up the order of arguments.
Then since C
defers the definition of self.name
and self.age
to parent classes, you immediately pass all arguments up the heirarchy using super().__init__(**kwargs)
. The best thing about inheritance is that child classes don't even need to know about the parameters it doesn't handle. The first parent class is A
, so self.name
is defined there. The next parent class in the method resolution order is B
, so from A
, you pass the remaining keyword arguments to B
, using super().__init__(**kwargs)
yet again.
class A(object):
def __init__(self, name, **kwargs):
self.name = name
super().__init__(**kwargs)
class B(object):
def __init__(self, age, **kwargs):
self.age = age
super().__init__(**kwargs) # this is actually not needed but in case you have other base classes after B, might come in handy
class C(A,B):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def display(self):
print(self.name, self.age)
c = C(name="xyz",age=12)
c.display()
Output:
xyz 12
CodePudding user response:
A simple solution would be to use kwargs
in all your initializers, and pass through the ones you don't care about.
class A:
def __init__(self, name, **kwargs):
super().__init__(**kwargs)
self.name = name
class B:
def __init__(self, age, **kwargs):
super().__init__(**kwargs)
self.age = age
class C(A, B):
def __init__(self, name, age, **kwargs):
super().__init__(name=name, age=age, **kwargs)
def display(self):
print(self.name, self.age)
By isolating the arguments you care about from kwargs
, you ensure that all kwargs
get consumed before you hit object
.
CodePudding user response:
I made a metaclass in my public library just for this purpose. Set the metaclass of the first base class.
It makes any inheriters automatically call its' bases __init__
s without having to worry about super()
calls allowing you to write cleaner code. It's also forgiving as it sets missing args to None
.
from generallibrary import AutoInitBases
class A(metaclass=AutoInitBases):
def __init__(self,name):
self.name=name
class B:
def __init__(self,age):
self.age=age
class C(A,B):
def __init__(self,name,age):
pass
def display(self):
print(self.name,self.age)
c=C("xyz",12)
c.display()
xyz 12
I don't care much about backward compatibility so make sure to lock the version if you install it. It supports python 3.8 and 3.9
pip install generallibrary==2.9.1