16.9. OOP Inheritance

  • Used to avoid code duplication

  • Subclass inherits all fields and methods from baseclass

parent
superclass
base class

Class from other classes inherits

child
subclass

Class which inherits from parent

inherit
derive

Class takes attributes and methods from parent

16.9.1. Single Inheritance

  • Account - base class

  • User inherits from Account

  • mark is and instance of User

  • mark is also an instance of Account (because User inherits from Account)

>>> class Account:
...     pass
>>>
>>> class User(Account):
...     pass
>>> mark = User()
>>>
>>> isinstance(mark, Account)
True
>>>
>>> isinstance(mark, User)
True

16.9.2. One Base, Many Subclasses

  • Account - base class

  • User inherits from Account

  • Admin inherits from Account

  • mark is and instance of User

  • mark is also an instance of Account (because User inherits from Account)

  • melissa is and instance of Admin

  • melissa is also an instance of Account (because Admin inherits from Account)

>>> class Account:
...     pass
>>>
>>> class User(Account):
...     pass
>>>
>>> class Admin(Account):
...     pass
>>> mark = User()
>>>
>>> isinstance(mark, Account)
True
>>>
>>> isinstance(mark, User)
True
>>>
>>> isinstance(mark, Admin)
False
>>> melissa = Admin()
>>>
>>> isinstance(melissa, Account)
True
>>>
>>> isinstance(melissa, User)
False
>>>
>>> isinstance(melissa, Admin)
True

16.9.3. Linear Inheritance

  • Account - base class

  • User inherits from Account

  • Admin inherits from User

  • mark is and instance of User

  • mark is also an instance of Account (because User inherits from Account)

  • melissa is and instance of Admin

  • melissa is also an instance of User (because Admin inherits from User)

  • melissa is also an instance of Account (because Admin inherits from User which inherits from Account)

>>> class Account:
...     pass
>>>
>>>
>>> class User(Account):
...     pass
>>>
>>> class Admin(User):
...     pass
>>> mark = User()
>>>
>>> isinstance(mark, Account)
True
>>>
>>> isinstance(mark, User)
True
>>>
>>> isinstance(mark, Admin)
False
>>> melissa = Admin()
>>>
>>> isinstance(melissa, Account)
True
>>>
>>> isinstance(melissa, User)
True
>>>
>>> isinstance(melissa, Admin)
True

16.9.4. Everything Inherits from Object

  • Everything in Python is an object

  • All built-in types inherit from object

  • All custom types inherit from object

  • Even classes inherit from object

  • object is where the original __init__, __str__, __repr__ methods are defined

All built-in types inherit from object:

>>> x = 1
>>> isinstance(x, object)
True
>>> x = 1.0
>>> isinstance(x, object)
True
>>> x = True
>>> isinstance(x, object)
True
>>> x = 'hello'
>>> isinstance(x, object)
True
>>> x = []
>>> isinstance(x, object)
True
>>> x = ()
>>> isinstance(x, object)
True
>>> x = set()
>>> isinstance(x, object)
True
>>> x = {}
>>> isinstance(x, object)
True

All custom types inherit from object:

>>> class User:
...     pass
>>>
>>> mark = User()
>>> isinstance(mark, object)
True

Even classes inherit from object:

>>> class User:
...     pass
>>>
>>> isinstance(User, object)
True

16.9.5. Methods

  • Child inherits all methods from parent

>>> class Parent:
...     def say_hello(self):
...         return 'Hello'
>>>
>>>
>>> class Child(Parent):
...     pass
>>>
>>>
>>> obj = Child()
>>> obj.say_hello()
'Hello'

16.9.6. Attributes

  • Child inherits all fields from parent

>>> class Parent:
...     def __init__(self):
...         self.firstname = 'Mark'
...         self.lastname = 'Watney'
>>>
>>>
>>> class Child(Parent):
...     pass
>>>
>>>
>>> obj = Child()
>>> vars(obj)
{'firstname': 'Mark', 'lastname': 'Watney'}

16.9.7. Use Case - 1

>>> class Person:
...     def __init__(self):
...         self.firstname = 'Mark'
...         self.lastname = 'Watney'
...
...     def say_hello(self):
...         return 'hello'
>>>
>>>
>>> class Astronaut(Person):
...     pass
>>>
>>> class Cosmonaut(Person):
...     pass

16.9.8. Use Case - 2

>>> class Iris:
...     sepal_length: float
...     sepal_width: float
...     petal_length: float
...     petal_width: float
...     species: str
...
...     def __init__(self, sepal_length, sepal_width,
...                  petal_length, petal_width, species):
...         self.sepal_length = sepal_length
...         self.sepal_width = sepal_width
...         self.petal_length = petal_length
...         self.petal_width = petal_width
...         self.species = species
>>>
>>>
>>> class Setosa(Iris):
...     pass
>>>
>>> class Versicolor(Iris):
...     pass
>>>
>>> class Virginica(Iris):
...     pass
>>>
>>>
>>> setosa = Setosa(
...     sepal_length=5.1,
...     sepal_width=3.5,
...     petal_length=1.4,
...     petal_width=0.2,
...     species='setosa')

16.9.9. Use Case - 1

>>> class Iris:
...     pass
>>>
>>>
>>> class Setosa(Iris):
...     pass
>>>
>>> class Versicolor(Iris):
...     pass
>>>
>>> class Virginica(Iris):
...     pass

16.9.10. References

16.9.11. Assignments

# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`

# %% About
# - Name: OOP Inheritance None
# - Difficulty: easy
# - Lines: 6
# - Minutes: 2

# %% English
# 1. Define class `Account` inheriting from object
# 2. Define class `User` inheriting from object
# 3. Define class `Admin` inheriting from object
# 4. Run doctests - all must succeed

# %% Polish
# 1. Zdefiniuj klasę `Account` dziedziczącą po object
# 2. Zdefiniuj klasę `User` dziedziczącą po object
# 3. Zdefiniuj klasę `Admin` dziedziczącą po object
# 4. Uruchom doctesty - wszystkie muszą się powieść

# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> from inspect import isclass

>>> assert isclass(Account)
>>> assert issubclass(Account, object)
>>> assert issubclass(Account, Account)
>>> assert not issubclass(Account, User)
>>> assert not issubclass(Account, Admin)

>>> assert isclass(User)
>>> assert issubclass(User, object)
>>> assert not issubclass(User, Account)
>>> assert issubclass(User, User)
>>> assert not issubclass(User, Admin)

>>> assert isclass(Admin)
>>> assert issubclass(Admin, object)
>>> assert not issubclass(Admin, Account)
>>> assert not issubclass(Admin, User)
>>> assert issubclass(Admin, Admin)
"""

# Define class `Account` inheriting from object
...

# Define class `User` inheriting from object
...

# Define class `Admin` inheriting from object
...


# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`

# %% About
# - Name: OOP Inheritance Single
# - Difficulty: easy
# - Lines: 6
# - Minutes: 2

# %% English
# 1. Define class `Account` inheriting from object
# 2. Define class `User` inheriting from `Account`
# 3. Define class `Admin` inheriting from `Account`
# 4. Run doctests - all must succeed

# %% Polish
# 1. Zdefiniuj klasę `Account` dziedziczącą po object
# 2. Zdefiniuj klasę `User` inheriting from `Account`
# 3. Zdefiniuj klasę `Admin` inheriting from `Account`
# 4. Uruchom doctesty - wszystkie muszą się powieść

# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> from inspect import isclass

>>> assert isclass(Account)
>>> assert issubclass(Account, object)
>>> assert issubclass(Account, Account)
>>> assert not issubclass(Account, User)
>>> assert not issubclass(Account, Admin)

>>> assert isclass(User)
>>> assert issubclass(User, object)
>>> assert issubclass(User, Account)
>>> assert issubclass(User, User)
>>> assert not issubclass(User, Admin)

>>> assert isclass(Admin)
>>> assert issubclass(Admin, object)
>>> assert issubclass(Admin, Account)
>>> assert not issubclass(Admin, User)
>>> assert issubclass(Admin, Admin)
"""

# Define class `Account` inheriting from object
...

# Define class `User` inheriting from `Account`
...

# Define class `Admin` inheriting from `Account`
...


# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`

# %% About
# - Name: OOP Inheritance Linear
# - Difficulty: easy
# - Lines: 6
# - Minutes: 2

# %% English
# 1. Define class `Account` inheriting from object
# 2. Define class `User` inheriting from `Account`
# 3. Define class `Admin` inheriting from `User`
# 4. Run doctests - all must succeed

# %% Polish
# 1. Zdefiniuj klasę `Account` dziedziczącą po object
# 2. Zdefiniuj klasę `User` inheriting from `Account`
# 3. Zdefiniuj klasę `Admin` inheriting from `User`
# 4. Uruchom doctesty - wszystkie muszą się powieść

# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> from inspect import isclass

>>> assert isclass(Account)
>>> assert issubclass(Account, object)
>>> assert issubclass(Account, Account)
>>> assert not issubclass(Account, User)
>>> assert not issubclass(Account, Admin)

>>> assert isclass(User)
>>> assert issubclass(User, object)
>>> assert issubclass(User, Account)
>>> assert issubclass(User, User)
>>> assert not issubclass(User, Admin)

>>> assert isclass(Admin)
>>> assert issubclass(Admin, object)
>>> assert issubclass(Admin, Account)
>>> assert issubclass(Admin, User)
>>> assert issubclass(Admin, Admin)
"""

# Define class `Account` inheriting from object
...

# Define class `User` inheriting from `Account`
...

# Define class `Admin` inheriting from `User`
...