You can create an abstract class by extending ABC which stands for "Abstract Base Classes" and can create the abstract method with @abstractmethod in the abstract class as shown below:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def sound(self):
pass
And, to use an abstract class, it should be extended by a child class and the child class should override the abstract method of the abstract class as shown below:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def sound(self):
pass
class Cat(Animal): # Extends "Animal" abstract class
def sound(self): # Overrides "sound()" abstract method
print("Meow!!")
obj = Cat()
obj.sound()
Output:
Meow!!
And, an abstract method can have code rather than pass
and can be called by a child class as shown below:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def sound(self):
print("Wow!!") # Here
class Cat(Animal):
def sound(self):
super().sound() # Here
obj = Cat()
obj.sound()
Output:
Wow!!
And, an abstract class can have the variables and non-abstract methods which can be called by a child class and non-abstract methods don't need to be overridden by a child class as shown below:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def sound(self):
pass
def __init__(self): # Here
self.name = "John" # Here
x = "Hello" # Here
def test1(self): # Here
print("Test1")
@classmethod # Here
def test2(cls):
print("Test2")
@staticmethod # Here
def test3():
print("Test3")
class Cat(Animal):
def sound(self):
print(self.name) # Here
print(super().x) # Here
super().test1() # Here
super().test2() # Here
super().test3() # Here
obj = Cat()
obj.sound()
Output:
John
Hello
Test1
Test2
Test3
And, you can define an abstract class and static methods and an abstract getter, setter and deleter in an abstract class as shown below. *@abstractmethod must be the innermost decorator otherwise error occurs and you can see my answer which explains more about an abstract getter, setter and deleter:
from abc import ABC, abstractmethod
class Person(ABC):
@classmethod
@abstractmethod # The innermost decorator
def test1(cls):
pass
@staticmethod
@abstractmethod # The innermost decorator
def test2():
pass
@property
@abstractmethod # The innermost decorator
def name(self):
pass
@name.setter
@abstractmethod # The innermost decorator
def name(self, name):
pass
@name.deleter
@abstractmethod # The innermost decorator
def name(self):
pass
Then, you need to override them in a child class as shown below:
class Student(Person):
def __init__(self, name):
self._name = name
@classmethod
def test1(cls): # Overrides abstract class method
print("Test1")
@staticmethod
def test2(): # Overrides abstract static method
print("Test2")
@property
def name(self): # Overrides abstract getter
return self._name
@name.setter
def name(self, name): # Overrides abstract setter
self._name = name
@name.deleter
def name(self): # Overrides abstract deleter
del self._name
Then, you can instantiate the child class and call them as shown below:
obj = Student("John") # Instantiates "Student" class
obj.test1() # Class method
obj.test2() # Static method
print(obj.name) # Getter
obj.name = "Tom" # Setter
print(obj.name) # Getter
del obj.name # Deleter
print(hasattr(obj, "name"))
Output:
Test1
Test2
John
Tom
False
And, if you try to instantiate an abstract class as shown below:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def sound(self):
pass
obj = Animal()
The error below occurs:
TypeError: Can't instantiate abstract class Animal with abstract methods sound
And, if you don't override the abstract method of an abstract class in a child class and you instantiate the child class as shown below:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def sound(self):
pass
class Cat(Animal):
pass # Doesn't override "sound()" abstract method
obj = Cat() # Here
The error below occurs:
TypeError: Can't instantiate abstract class Cat with abstract methods sound
And, if you define an abstract method in the non-abstract class which doesn't extend ABC
, the abstract method is a normal instance method so there are no errors even if the non-abstract class is instantiated and even if a child class doesn't override the abstract method of the non-abstract class as shown below:
from abc import ABC, abstractmethod
class Animal: # Doesn't extend "ABC"
@abstractmethod # Here
def sound(self):
print("Wow!!")
class Cat(Animal):
pass # Doesn't override "sound()" abstract method
obj1 = Animal() # Here
obj1.sound()
obj2 = Cat() # Here
obj2.sound()
Output:
Wow!!
Wow!!
In addition, you can replace Cat
class extending Animal
class below:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def sound(self):
pass
# ↓↓↓ Here ↓↓↓
class Cat(Animal):
def sound(self):
print("Meow!!")
# ↑↑↑ Here ↑↑↑
print(issubclass(Cat, Animal))
With this code having register() below:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def sound(self):
pass
# ↓↓↓ Here ↓↓↓
class Cat:
def sound(self):
print("Meow!!")
Animal.register(Cat)
# ↑↑↑ Here ↑↑↑
print(issubclass(Cat, Animal))
Then, both of the code above outputs the same result below showing Cat
class is the subclass of Animal
class:
True