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
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:
class
statement. That is, given class A(B, C, D)
, the MRO for A
will have B
before C
, which will be before D
. (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")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With