'"Cannot create a consistent method resolution order" inheriting from another child class
I am revising OOP in Python and tried inheriting attributes from another child class but I couldn't figure out how or if it is possible. Here is what I have so far:
class Employee:
def __init__(self, first, last, pay):
self.first = first
self.last = last
self.pay = pay
def increase_pay(self, multiplier):
self.pay = int(self.pay * multiplier)
class Developer(Employee):
def __init__(self, first, last, pay, prog_lang):
Employee.__init__(self, first, last, pay)
self.prog_lang = prog_lang
self.email = first.lower() + '.' + last.lower() + '@outlook.com'
class BetaTester(Employee, Developer):
def __init__(self, first, last, pay, prog_lang, platform):
self.platform = platform
The error I receive is:
Traceback (most recent call last):
File "main.py", line 33, in <module>
class BetaTester(Employee, Developer):
TypeError: Cannot create a consistent method resolution
order (MRO) for bases Employee, Developer
Solution 1:[1]
The method resolution order (MRO) is defined by the C3 linearization algorithm, which sounds complicated but it really boils down to this: the class, its parents, their parents, etc need to be placed in a list subject to two conditions:
- Each class appears before its parent(s)
- If a class inherits from more than one class, its parents appear in the same
order as they do in
classstatement. That is, givenclass A(B, C, D), the MRO forAwill haveBbeforeC, which will be beforeD. (A, of course, appears before all 3)
You should be able to see the problem: by this algorithm, the MRO for BetaTester has to include Developer before Employer according to the first rule, but Employer has to come before Developer according to the second rule. In this case, you can simply swap the two to fix the problem, but there's never any reason to inherit from a class A and another class the inherits from A. Just drop A altogether.
# Developer is already a descendent of Employee, so BetaTester will be, too
class BetaTester(Developer):
...
To make sure each class's __init__ method is called, use super to make sure each __init__ calls the next one in the chain. The most important rule here is to make sure that if a class adds arguments to __init__, it has to make sure not to pass them on to the next __init__. At the same time, it has to accept arbitrary keywords arguments and be sure to pass them on. Keyword arguments make it simpler to focus on the arguments you need to deal with, and just pass on the ones you don't.
class Employee:
def __init__(self, first, last, pay, **kwargs):
super().__init__(**kwargs)
self.first = first
self.last = last
self.pay = pay
def increase_pay(self, multiplier):
self.pay = int(self.pay * multiplier)
class Developer(Employee):
def __init__(self, prog_lang, **kwargs):
super().__init__(**kwargs)
self.prog_lang = prog_lang
self.email = "{}.{}@outlook.com".format(self.first.lower(), self.last.lower())
class BetaTester(Developer):
def __init__(self, platform, **kwargs):
super().__init__(**kwargs)
self.platform = platform
b = BetaTester(first="Bob", last="Jones", pay=90000, prog_lang="Python", platform="Unix")
Solution 2:[2]
@MehrdadEP has answered very well
I think i should make it easy
suppose there are 2 classes A and B
B inherits from A
Now you are creating a new class C
if you inherit from B you are already inheriting from A. no need to write that in class C(A,B)
observe C(B,A) will not give you error But C(A,B) will
Another thing is you should use Super().__init__() instead of Employee.__init__()
This may not be handy when doing Hybrid Inheritance due to more than 1 different super classes where you would have to call classname1.__init__() , classname2.__init__() and so on
also make sure if you want the attributes defined in SuperClass then call the classname.__init__() so that they are defined in new class's scope otherwise
you will get an error
for example
print(b1_1.first) will give an error
to resolve that use Developer.__init__(self, first, last, pay, prog_lang)
and don't forget the self in this Developer.__init__ calling from subclass __init__
Solution 3:[3]
- use
super()in__init__method of sub classes - Your
BetaTesteris inheriting fromEmployeeandDeveloper. BecauseDeveloperalready inherits fromEmployeePython now cannot determine what class to look methods up on first. You don't need to name all base classes ofDeveloperhere; just inherit from that one class.
here is your fixed code:
class Employee:
def __init__(self, first, last, pay):
self.first = first
self.last = last
self.pay = pay
def increase_pay(self, multiplier):
self.pay = int(self.pay * multiplier)
emp_1 = Employee('David', 'Jackson', 35000)
print (emp_1.pay)
emp_1.increase_pay(1.2)
print (emp_1.pay)
class Developer(Employee):
def __init__(self, first, last, pay, prog_lang):
super().__init__(first, last, pay)
self.prog_lang = prog_lang
self.email = first.lower() + '.' + last.lower() + '@outlook.com'
dev_1 = Developer('James', 'McCarthy', 70000, 'C++',)
print(dev_1.first)
print(dev_1.email)
class BetaTester(Developer):
def __init__(self,first, last, pay, prog_lang, platform):
self.platform = platform
bt_1 = BetaTester('Jonas', 'Andersen', 45000, 'C#', 'Mobile')
print(bt_1.platform)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Neuron |
| Solution 2 | |
| Solution 3 | Neuron |
