Create a subclass

Documentation

  1. Inheritance in the Python Tutorial
  2. super
  3. issubclass
  4. mro method: method resolution order

Add a method to the subclass

To find the temperature in fahrenheit, count how many times cricket chirps in 15 seconds and add 39.

import sys

class Cricket(object):
    def __init__(self, chirps):
        if not isinstance(chirps, int):
            raise TypeError(f"chirps must be int, not {type(chirps)}")
        if chirps < 0:
            raise ValueError(f"chirps must be non-negative, not {chirps}")
        self.chirps = chirps

    def fahrenheit(self):
        return self.chirps + 39

    def __str__(self):
        return f"cricket({self.chirps})"


class MetricCricket(Cricket):
    def __init__(self, chirps):
        super().__init__(chirps)                #or Cricket.__init__(self, chirps)

    def celsius(self):
        return (self.fahrenheit() - 32) * 5 / 9 #or return (Cricket.fahrenheit(self) - 32) * 5 / 9
                                                #or return (super().fahrenheit() - 32) * 5 / 9
    def __str__(self):
        return f"MetricCricket({self.chirps})"


class KelvinCricket(MetricCricket):
    def __init__(self, chirps):
        super().__init__(chirps)

    def kelvin(self):
        return self.celsius() + 273.15

    def __str__(self):
        return f"KelvinKricket({self.chirps})"


buddy = Cricket(33)
print(f"fahrenheit = {buddy.fahrenheit()}")
print()

mc = MetricCricket(33)
print(f"fahrenheit = {mc.fahrenheit()}")
print(f"celsius    = {mc.celsius()}")
print()

kc = KelvinCricket(33)
print(f"fahrenheit = {kc.fahrenheit()}")
print(f"celsius    = {kc.celsius()}")
print(f"kelvin     = {kc.kelvin()}")
print()

print("Is class MetricCricket a subclass of class Cricket? ", end = "")
print(issubclass(MetricCricket, Cricket))
print()

print("Class KelvinCricket and its superclasses are")
for i, cls in enumerate(KelvinCricket.mro(), start = 1): #method resolution order
    print(i, cls)                                        #cls is a type object

sys.exit(0)
fahrenheit = 72

fahrenheit = 72
celsius    = 22.22222222222222

fahrenheit = 72
celsius    = 22.22222222222222
kelvin     = 295.3722222222222

Is class MetricCricket a subclass of class Cricket? True

Class KelvinCricket and its superclasses are
1 <class '__main__.KelvinCricket'>
2 <class '__main__.MetricCricket'>
3 <class '__main__.Cricket'>
4 <class 'object'>

Add an attribute to the subclass

class Amniote(object):
    def __init__(self, amnion):
        self.amnion = amnion


class Synapsid(Amniote):
    def __init__(self, amnion, synapsidOpening):
        super().__init__(amnion)
        self.synapsidOpening = synapsidOpening


class Mammal(Synapsid):
    def __init__(self, amnion, synapsidOpening, bones):
        super().__init__(amnion, synapsidOpening)
        self.bones = bones #middle ear bones: incus, malleus, stapes


class Placental(Mammal):
    def __init__(self, amnion, synapsidOpening, bones, placenta):
        super().__init__(amnion, synapsidOpening, bones)
        self.placenta = placenta


amniote = Amniote("amnion")
print(f"amnion          = {amniote.amnion}")
print()

synapsid = Synapsid("amnion", "synapsidOpening")
print(f"amnion          = {synapsid.amnion}")
print(f"synapsidOpening = {synapsid.synapsidOpening}")
print()

mammal = Mammal("amnion", "synapsidOpening", "bones")
print(f"amnion          = {mammal.amnion}")
print(f"synapsidOpening = {mammal.synapsidOpening}")
print(f"bones           = {mammal.bones}")
print()

placental = Placental("amnion", "synapsidOpening", "bones", "placenta")
print(f"amnion          = {placental.amnion}")
print(f"synapsidOpening = {placental.synapsidOpening}")
print(f"bones           = {placental.bones}")
print(f"placenta        = {placental.placenta}")
print()
amnion          = amnion

amnion          = amnion
synapsidOpening = synapsidOpening

amnion          = amnion
synapsidOpening = synapsidOpening
bones           = bones

amnion          = amnion
synapsidOpening = synapsidOpening
bones           = bones
placenta        = placenta

Inheritance in the Python Standard Library

Class bool is a subclass of class int

If you would prefer to list the classes in the reverse order, simply change bool.mro() to reversed(bool.mro()).

for i, cls in enumerate(bool.mro(), start = 1):
    print(i, cls)   #cls is a type object
1 <class 'bool'>
2 <class 'int'>
3 <class 'object'>

Class datetime.datetime is a subclass of class datetime.date

Why isn’t class datetime.datetime also a subclass of class datetime.time?

import datetime

for i, cls in enumerate(datetime.datetime.mro(), start = 1):
    print(i, cls)
1 <class 'datetime.datetime'>
2 <class 'datetime.date'>
3 <class 'object'>

Class TypeError is a subclass of class Exception

for i, cls in enumerate(TypeError.mro(), start = 1):
    print(i, cls)
1 <class 'TypeError'>
2 <class 'Exception'>
3 <class 'BaseException'>
4 <class 'object'>

Class ZeroDivisionError is a subclass of class Exception

for i, cls in enumerate(ZeroDivisionError.mro(), start = 1):
    print(i, cls)
1 <class 'ZeroDivisionError'>
2 <class 'ArithmeticError'>
3 <class 'Exception'>
4 <class 'BaseException'>
5 <class 'object'>

The open function returns an object of a subclass of class io.IOBase

import sys

try:
    infile = open("filename.txt")
except BaseException as error:
    print(error, file = sys.stderr)
    sys.exit(1)

for i, cls in enumerate(type(infile).mro(), start = 1):
    print(i, cls)

infile.close()
1 <class '_io.TextIOWrapper'>
2 <class '_io._TextIOBase'>
3 <class '_io._IOBase'>
4 <class 'object'>

Changing the call to open to

    infile = open("filename.jpg", "rb")   #read binary
1 <class '_io.BufferedReader'>
2 <class '_io._BufferedIOBase'>
3 <class '_io._IOBase'>
4 <class 'object'>
    infile = open("filename.jpg", "rb", buffering = 0)
1 <class '_io.FileIO'>
2 <class '_io._RawIOBase'>
3 <class '_io._IOBase'>
4 <class 'object'>

Standard i/o

import sys

for i, cls in enumerate(type(sys.stdin).mro(), start = 1): #also try sys.stdout, sys.stderr
    print(cls)
1 <class 'idlelib.run.PseudoInputFile'>
2 <class 'idlelib.run.PseudoFile'>
3 <class 'io.TextIOBase'>
4 <class '_io._TextIOBase'>
5 <class 'io.IOBase'>
6 <class '_io._IOBase'>
7 <class 'object'>

Open a URL

import urllib.request

response = urllib.request.urlopen("http://python.org/")

for i, cls in enumerate(type(response).mro(), start = 1):
    print(i, cls)

response.close()
1 <class 'http.client.HTTPResponse'>
2 <class 'io.BufferedIOBase'>
3 <class '_io._BufferedIOBase'>
4 <class 'io.IOBase'>
5 <class '_io._IOBase'>
6 <class 'object'>

Class threading._MainThread is a subclass of class threading.Thread

import threading

for i, cls in enumerate(threading._MainThread.mro(), start = 1):
    print(i, cls)
1 <class 'threading._MainThread'>
2 <class 'threading.Thread'>
3 <class 'object'>