4.1. Inheritance About

  • no inheritance

  • single inheritance

  • multilevel inheritance

  • multiple inheritance (mixin classes)

  • aggregation

  • composition

single inheritance

One class inherits from one other class. Has one parent.

multilevel inheritance

One class inherits from other class, and yet another class inherits from it. This creates hierarchical structure.

multiple inheritance
mixin classes

One class derives from several other classes at once.

4.1.1. No Inheritance

../../_images/inheritance-about-none.png
class User:
    pass


class Staff:
    pass


class Admin:
    pass

4.1.2. Single Inheritance

../../_images/inheritance-about-single.png
class User:
    pass


class Staff(User):
    pass


class Admin(User):
    pass

4.1.3. Multilevel Inheritance

../../_images/inheritance-about-multilevel.png
class User:
    pass


class Staff(User):
    pass


class Admin(Staff):
    pass

4.1.4. Multiple Inheritance

../../_images/inheritance-about-multiple.png
class User:
    pass


class Staff:
    pass


class Admin(User, Staff):
    pass

4.1.5. Aggregation

../../_images/inheritance-about-aggregation.png
class User:
    pass


class Staff:
    pass


class Admin:
    def __init__(self):
        self.permissions = [User(), Staff()]

4.1.6. Composition

../../_images/inheritance-about-composition.png
class User:
    pass


class Staff:
    pass


class Admin:
    def __init__(self):
        self.user = User()
        self.staff = Staff()

4.1.7. Further Reading

4.1.8. Assignments

Code 4.48. Solution
"""
* Assignment: Inheritance About None
* Complexity: easy
* Lines of code: 8 lines
* Time: 3 min

English:
    1. Define classe `Account`
    2. Define classe `User`
    3. Define classe `Admin`
    4. Do not use inheritance
    5. Assignment demonstrates syntax, so do not add any attributes and methods
    6. Run doctests - all must succeed

Polish:
    1. Zdefiniuj klasę `Account`
    2. Zdefiniuj klasę `User`
    3. Zdefiniuj klasę `Admin`
    4. Nie używaj dziedziczenia
    5. Zadanie demonstruje składnię, nie dodawaj żadnych atrybutów i metod
    6. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0
    >>> from inspect import isclass

    >>> assert isclass(Account)
    >>> assert isclass(User)
    >>> assert isclass(Admin)

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

    >>> assert len(Account.__subclasses__()) == 0
    >>> assert len(User.__subclasses__()) == 0
    >>> assert len(Admin.__subclasses__()) == 0
"""

# Define classe `Account`
...

# Define classe `User`
...

# Define classe `Admin`
...

Code 4.49. Solution
"""
* Assignment: Inheritance About Single
* Complexity: easy
* Lines of code: 8 lines
* Time: 3 min

English:
    1. Define class `Account`
    2. Define classe `User` inheriting from `Account`
    3. Define classe `Admin` inheriting from `Account`
    4. Use single inheritance
    5. Assignment demonstrates syntax, so do not add any attributes and methods
    6. Run doctests - all must succeed

Polish:
    1. Zdefiniuj klasę `Account`
    2. Zdefiniuj klasę `User` dziedziczacą po `Account`
    3. Zdefiniuj klasę `Admin` dziedziczacą po `Account`
    4. Użyj pojedynczego dziedziczenia
    5. Zadanie demonstruje składnię, nie dodawaj żadnych atrybutów i metod
    6. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0
    >>> from inspect import isclass

    >>> assert isclass(Account)
    >>> assert isclass(User)
    >>> assert isclass(Admin)

    >>> assert issubclass(User, Account)
    >>> assert issubclass(Admin, Account)

    >>> assert len(Account.__subclasses__()) == 2
    >>> assert len(User.__subclasses__()) == 0
    >>> assert len(Admin.__subclasses__()) == 0
"""

# Define class `Account`
...

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

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

Code 4.50. Solution
"""
* Assignment: Inheritance About Multilevel
* Complexity: easy
* Lines of code: 8 lines
* Time: 3 min

English:
    1. Define class `Account`
    2. Define classe `User` inheriting from `Account`
    3. Define classe `Admin` inheriting from `User`
    4. Use multilevel inheritance
    5. Assignment demonstrates syntax, so do not add any attributes and methods
    6. Run doctests - all must succeed

Polish:
    1. Zdefiniuj klasę `Account`
    2. Zdefiniuj klasę `User` dziedziczacą po `Account`
    3. Zdefiniuj klasę `Admin` dziedziczacą po `User`
    4. Użyj wielopoziomowego dziedziczenia
    5. Zadanie demonstruje składnię, nie dodawaj żadnych atrybutów i metod
    6. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0
    >>> from inspect import isclass

    >>> assert isclass(Account)
    >>> assert isclass(User)
    >>> assert isclass(Admin)

    >>> assert issubclass(User, Account)
    >>> assert issubclass(Admin, User)
    >>> assert issubclass(Admin, Account)

    >>> assert len(Account.__subclasses__()) == 1
    >>> assert len(User.__subclasses__()) == 1
    >>> assert len(Admin.__subclasses__()) == 0
"""

# Define class `Account`
...

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

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

Code 4.51. Solution
# TODO: poprawić zadanie aby było spójne z pozostałymi
"""
* Assignment: Inheritance About Multiple
* Complexity: easy
* Lines of code: 1 lines
* Time: 2 min

English:
    1. Create class `MyAccount` from classes `Account`, `User`, `Admin`
    2. Use mixins classes
    3. Assignment demonstrates syntax, so do not add any attributes and methods
    4. Run doctests - all must succeed

Polish:
    1. Stwórz klasę `MyAccount` z klas `Account`, `User`, `Admin`
    2. Użyj klas domieszkowych (mixin)
    3. Zadanie demonstruje składnię, nie dodawaj żadnych atrybutów i metod
    4. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0
    >>> from inspect import isclass

    >>> assert isclass(Account)
    >>> assert isclass(User)
    >>> assert isclass(Admin)
    >>> assert isclass(MyAccount)
    >>> assert issubclass(MyAccount, Account)
    >>> assert issubclass(MyAccount, User)
    >>> assert issubclass(MyAccount, Admin)

    >>> assert len(Account.__subclasses__()) == 1
    >>> assert len(User.__subclasses__()) == 1
    >>> assert len(Admin.__subclasses__()) == 1
    >>> assert len(MyAccount.__subclasses__()) == 0
"""

# Create classes `MyAccount`, `Account`, `User`,  `Admin`
# Use mixins classes, do not define attributes
class Account:
    pass


class User:
    pass


class Admin:
    pass


class MyAccount:
    pass


Code 4.52. Solution
# TODO: poprawić zadanie aby było spójne z pozostałymi
"""
* Assignment: Inheritance About Composition
* Complexity: easy
* Lines of code: 2 lines
* Time: 3 min

English:
    1. Define class `MyAccount` with attribute `type: Account`
    2. Use composition
    3. Allow for setting type `User` or `Admin` in `__init__()` method
    4. Assignment demonstrates syntax
    5. Run doctests - all must succeed

Polish:
    1. Zdefiniuj klasę `MyAccount` z atrybutem `type: Account`
    2. Użyj kompozycji
    3. Pozwól na ustawianie typu `User` or `Admin` w metodzie `__init__()`
    4. Zadanie demonstruje składnię
    5. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0
    >>> from inspect import isclass

    >>> assert isclass(User)
    >>> assert isclass(Admin)
    >>> assert isclass(Account)
    >>> assert isclass(MyAccount)

    >>> result = MyAccount()
    >>> assert hasattr(result, 'type')

    >>> result = MyAccount()
    >>> assert hasattr(result, 'type')
    >>> assert not isclass(result.type)
    >>> assert isinstance(result.type, Account)
    >>> assert not isinstance(result.type, User)
    >>> assert not isinstance(result.type, Admin)

    >>> result = MyAccount(type=Account)
    >>> assert hasattr(result, 'type')
    >>> assert not isclass(result.type)
    >>> assert isinstance(result.type, Account)
    >>> assert not isinstance(result.type, User)
    >>> assert not isinstance(result.type, Admin)

    >>> result = MyAccount(type=User)
    >>> assert hasattr(result, 'type')
    >>> assert not isclass(result.type)
    >>> assert isinstance(result.type, Account)
    >>> assert isinstance(result.type, User)
    >>> assert not isinstance(result.type, Admin)

    >>> result = MyAccount(type=Admin)
    >>> assert hasattr(result, 'type')
    >>> assert not isclass(result.type)
    >>> assert isinstance(result.type, Account)
    >>> assert not isinstance(result.type, User)
    >>> assert isinstance(result.type, Admin)
"""

class Account:
    pass


class User(Account):
    pass


class Admin(Account):
    pass


# Use composition
# Define class `MyAccount` with attribute `type: Account`
# Allow for setting type `User` or `Admin` in `__init__()` method
class MyAccount:
    pass