Inheritance¶
Extending Existing Classes¶
Person
is not enoughWant
Employee
is-a
Person
, but with additional features⟶ Implementation inheritance
class Person: def __init__(self, firstname, lastname): self.firstname = firstname self.lastname = lastname def fullname(self): return f'{self.firstname} {self.lastname}' class Employee(Person): # <--- is-a Person pass
Creating an instance of Employee
…
Employee
: no__init__()
Person
: found⟶
Person.__init__()
calledemp = Employee('Joerg', 'Faschingbauer') emp.fullname()
'Joerg Faschingbauer'
Additional Feature: Salary¶
Employee
needs its own constructor (addedsalary
)Calls base classe constructor ⟶
super()
class Employee(Person): def __init__(self, firstname, lastname, salary): super().__init__(firstname, lastname) # <--- Person.__init__() self.salary = salary def title(self): return f'{self.fullname()} ({self.salary})'
Now calling
Employee.__init__()
…… which in turn calls
Person.__init__()
emp = Employee('Joerg', 'Faschingbauer', 6000) emp.title()
'Joerg Faschingbauer (6000)'
Want Manager¶
Another class, Manager
, in the tree …
class Manager(Employee):
def __init__(self, firstname, lastname, salary, employees):
super().__init__(firstname, lastname, salary) # <--- Employee.__init__()
self.employees = employees
def add_employee(self, employee):
self.employees.append(employee)
def title(self):
title = super().title()
return title + f' (manages {len(self.employees)} employees)'
Composing a number of objects into a Manager
instance …
joerg = Employee('Joerg', 'Faschingbauer', 6000)
mgr = Manager('Isolde', 'Haubentaucher', 10000, [joerg])
caro = Employee('Caro', 'Faschingbauer', 5000)
mgr.add_employee(caro)
mgr.title()
'Isolde Haubentaucher (10000) (manages 2 employees)'
Introspecting Inheritance: isinstance()
, issubclass()
¶
isinstance(object, cls)
: isobject
an instance ofcls
(or of a base class thereof)?issubclass(cls, parentcls)
: iscls
a subclass ofparentcls
?Funnily a class is considered a subclass of itself
isinstance()
¶
Obviously an Employee
instance is an Employee
instance:
joerg = Employee('Joerg', 'Faschingbauer', 6000)
isinstance(joerg, Employee)
True
He is also a Person
:
isinstance(joerg, Person)
True
But not a Manager
:
isinstance(joerg, Manager)
False
issubclass()
¶
Manager
is-a Person
issubclass(Manager, Person)
True
… but not the other way around:
issubclass(Person, Manager)
False
Funnily, Person
is-a Person
:
issubclass(Person, Person)
True
Add __str__()
, Creatively, After The Fact¶
Unrelated, but fun: add class methods dynamically …
Person.__str__ = Person.fullname
Employee.__str__ = Employee.title
Manager.__str__ = Manager.title
joerg = Employee('Joerg', 'Faschingbauer', 6000)
mgr = Manager('Isolde', 'Haubentaucher', 10000, [joerg])
caro = Employee('Caro', 'Faschingbauer', 5000)
mgr.add_employee(caro)
print('joerg:', joerg)
print('mgr:', mgr)
joerg: Joerg Faschingbauer (6000)
mgr: Isolde Haubentaucher (10000) (manages 2 employees)