17.10. 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
17.10.1. Problem
>>> class User:
... def login(self):
... print('ok')
>>>
>>>
>>> class Admin:
... def login(self):
... print('ok')
>>> alice = User()
>>> alice.login()
ok
>>>
>>> bob = Admin()
>>> bob.login()
ok
17.10.2. Solution
>>> class Account:
... def login(self):
... print('ok')
>>>
>>>
>>> class User(Account):
... pass
>>>
>>> class Admin(Account):
... pass
>>> alice = User()
>>> alice.login()
ok
>>>
>>> bob = Admin()
>>> bob.login()
ok
17.10.3. No Inheritance
Accountinherits fromobjectUserinherits fromobjectAdmininherits fromobject
>>> class Account:
... pass
>>>
>>> class User:
... pass
>>>
>>> class Admin:
... pass
>>> alice = Admin()
>>>
>>> isinstance(alice, Account)
False
>>>
>>> isinstance(alice, User)
False
>>>
>>> isinstance(alice, Admin)
True
17.10.4. Single Inheritance
Accountinherits fromobjectUserinherits fromAccountAdmininherits fromAccount
>>> class Account:
... pass
>>>
>>> class User(Account):
... pass
>>>
>>> class Admin(Account):
... pass
>>> alice = Admin()
>>>
>>> isinstance(alice, Account)
True
>>>
>>> isinstance(alice, User)
False
>>>
>>> isinstance(alice, Admin)
True
17.10.5. Linear Inheritance
Accountinherits fromobjectUserinherits fromAccountAdmininherits fromUseraliceis and instance ofAdminaliceis also an instance ofUser(becauseAdmininherits fromUser)aliceis also an instance ofAccount(becauseAdmininherits fromUserwhich inherits fromAccount)
>>> class Account:
... pass
>>>
>>> class User(Account):
... pass
>>>
>>> class Admin(User):
... pass
>>> alice = Admin()
>>>
>>> isinstance(alice, Account)
True
>>>
>>> isinstance(alice, User)
True
>>>
>>> isinstance(alice, Admin)
True
17.10.6. MRO
Account.mro()User.mro()Admin.mro()
>>> class Account:
... pass
>>>
>>> class User(Account):
... pass
>>>
>>> class Admin(User):
... pass
>>> Account.mro()
[<class '__main__.Account'>, <class 'object'>]
>>>
>>> User.mro()
[<class '__main__.User'>, <class '__main__.Account'>, <class 'object'>]
>>>
>>> Admin.mro()
[<class '__main__.Admin'>, <class '__main__.User'>, <class '__main__.Account'>, <class 'object'>]
17.10.7. 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
objectis where the original__init__,__str__,__repr__methods are defined
All built-in types inherit from object:
>>> int.mro()
[<class 'int'>, <class 'object'>]
>>> float.mro()
[<class 'float'>, <class 'object'>]
>>> bool.mro()
[<class 'bool'>, <class 'int'>, <class 'object'>]
>>> str.mro()
[<class 'str'>, <class 'object'>]
>>> tuple.mro()
[<class 'tuple'>, <class 'object'>]
>>> list.mro()
[<class 'list'>, <class 'object'>]
>>> set.mro()
[<class 'set'>, <class 'object'>]
>>> dict.mro()
[<class 'dict'>, <class 'object'>]
17.10.8. Bool/Int Inheritance
boolinherits fromintintinherits fromobject
>>> bool.mro()
[<class 'bool'>, <class 'int'>, <class 'object'>]
>>>
>>> int.mro()
[<class 'int'>, <class 'object'>]
>>> type(True)
<class 'bool'>
>>>
>>> type(1)
<class 'int'>
>>> isinstance(True, bool)
True
>>>
>>> isinstance(True, int)
True
>>>
>>> isinstance(True, object)
True
>>> isinstance(1, bool)
False
>>>
>>> isinstance(1, int)
True
>>>
>>> isinstance(1, object)
True
17.10.9. Use Case - 1
>>> class Iris:
... pass
>>>
>>>
>>> class Setosa(Iris):
... pass
>>>
>>> class Versicolor(Iris):
... pass
>>>
>>> class Virginica(Iris):
... pass
17.10.10. Use Case - 2
>>> class Account:
... def login(self): ...
... def logout(self): ...
... def is_authenticated(self): ...
>>>
>>> class User(Account):
... def set_name(self, firstname, lastname): ...
... def get_name(self): ...
>>>
>>> class Admin(User):
... def add_user(self): ...
... def edit_user(self): ...
... def list_user(self): ...
... def remove_user(self): ...
17.10.11. Use Case - 3
>>> class Account:
... pass
>>>
>>> class User(Account):
... pass
>>>
>>> class Admin(User):
... pass
>>> alice = User()
>>>
>>> isinstance(alice, object)
True
>>>
>>> isinstance(alice, Account)
True
>>>
>>> isinstance(alice, User)
True
>>>
>>> isinstance(alice, Admin)
False
>>> bob = Admin()
>>>
>>> isinstance(bob, object)
True
>>>
>>> isinstance(bob, Account)
True
>>>
>>> isinstance(bob, User)
True
>>>
>>> isinstance(bob, Admin)
True
17.10.12. References
17.10.13. Assignments
# %% About
# - Name: OOP Inheritance None
# - Difficulty: easy
# - Lines: 6
# - Minutes: 2
# %% 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
# %% 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ść
# %% Expected
# TODO: Write expected result
# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python has an is invalid version; expected: `3.9` or newer.'
>>> from inspect import isclass
>>> assert isclass(Account), \
'Object `Account` has an invalid type; expected: `class`.'
>>> assert issubclass(Account, object)
>>> assert issubclass(Account, Account)
>>> assert not issubclass(Account, User)
>>> assert not issubclass(Account, Admin)
>>> assert isclass(User), \
'Object `User` has an invalid type; expected: `class`.'
>>> assert issubclass(User, object)
>>> assert not issubclass(User, Account)
>>> assert issubclass(User, User)
>>> assert not issubclass(User, Admin)
>>> assert isclass(Admin), \
'Object `Admin` has an invalid type; expected: `class`.'
>>> assert issubclass(Admin, object)
>>> assert not issubclass(Admin, Account)
>>> assert not issubclass(Admin, User)
>>> assert issubclass(Admin, Admin)
"""
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -f -v myfile.py`
# %% Imports
# %% Types
Account: type
User: type
Admin: type
# %% Data
# %% Result
# %% About
# - Name: OOP Inheritance Single
# - Difficulty: easy
# - Lines: 6
# - Minutes: 2
# %% 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
# %% 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ść
# %% Expected
# TODO: Write expected result
# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python has an is invalid version; expected: `3.9` or newer.'
>>> from inspect import isclass
>>> assert isclass(Account), \
'Object `Account` has an invalid type; expected: `class`.'
>>> assert issubclass(Account, object)
>>> assert issubclass(Account, Account)
>>> assert not issubclass(Account, User)
>>> assert not issubclass(Account, Admin)
>>> assert isclass(User), \
'Object `User` has an invalid type; expected: `class`.'
>>> assert issubclass(User, object)
>>> assert issubclass(User, Account)
>>> assert issubclass(User, User)
>>> assert not issubclass(User, Admin)
>>> assert isclass(Admin), \
'Object `Admin` has an invalid type; expected: `class`.'
>>> assert issubclass(Admin, object)
>>> assert issubclass(Admin, Account)
>>> assert not issubclass(Admin, User)
>>> assert issubclass(Admin, Admin)
"""
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -f -v myfile.py`
# %% Imports
# %% Types
Account: type
User: type
Admin: type
# %% Data
# %% Result
# %% About
# - Name: OOP Inheritance Linear
# - Difficulty: easy
# - Lines: 6
# - Minutes: 2
# %% 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
# %% 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ść
# %% Expected
# TODO: Write expected result
# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python has an is invalid version; expected: `3.9` or newer.'
>>> from inspect import isclass
>>> assert isclass(Account), \
'Object `Account` has an invalid type; expected: `class`.'
>>> assert issubclass(Account, object)
>>> assert issubclass(Account, Account)
>>> assert not issubclass(Account, User)
>>> assert not issubclass(Account, Admin)
>>> assert isclass(User), \
'Object `User` has an invalid type; expected: `class`.'
>>> assert issubclass(User, object)
>>> assert issubclass(User, Account)
>>> assert issubclass(User, User)
>>> assert not issubclass(User, Admin)
>>> assert isclass(Admin), \
'Object `Admin` has an invalid type; expected: `class`.'
>>> assert issubclass(Admin, object)
>>> assert issubclass(Admin, Account)
>>> assert issubclass(Admin, User)
>>> assert issubclass(Admin, Admin)
"""
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -f -v myfile.py`
# %% Imports
# %% Types
Account: type
User: type
Admin: type
# %% Data
# %% Result