What is the ABC of Python? It stands for the abstract base class and is a concept in Python classes based on abstraction. Abstraction is an integral part of object-oriented programming.
Abstraction is what we call hiding the internal process of the program from the users. Take the example of the computer mouse where we click the left or right button and something respective of it happens or scroll the mouse wheel and a specific task happens. We are unaware of the internal functionality but we do know that clicking this button will do our job.
In abstraction, users are unaware of the internal functionality but are familiar with the purpose of the method. If we take an example of aΒ datetime
Β module, we do know that running theΒ datetime.now()
Β function will return the current date and time but are unaware of how this happens.
ABC in Python
Python is not a fully object-oriented programming language but it supports the features like abstract classes and abstraction. We cannot create abstract classes directly in Python, so Python provides a module called abc
that provides the infrastructure for defining the base of Abstract Base Classes(ABC).
What are abstract base classes? They provide a blueprint for concrete classes. They are just defined but not implemented rather they require subclasses for implementation.
Defining ABC
Let’s understand with an example how we can define an abstract class with an abstract method inside it.
1 2 3 4 5 6 7 |
from abc import ABC, abstractmethod class Friend(ABC): @abstractmethod def role(self): pass |
The class Friend
derived from the ABC
class from the abc
module that makes it an abstract class and then within the class, a decorator @abstractmethod
is defined to indicate that the function role
is an abstract method.
abc
module has another class ABCMeta
which is used to create abstract classes.
1 2 3 4 5 6 7 |
from abc import ABCMeta, abstractmethod class Friend(metaclass=ABCMeta): @abstractmethod def role(self): pass |
ABC in action
Now we’ll see how to make an abstract class and abstract method and then implement it inside the concrete classes through inheritance.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
from abc import ABC, abstractmethod # Defining abstract class class Friends(ABC): """abstract method decorator to indicate that the method right below is an abstract method.""" @abstractmethod def role(self): pass # Concrete derived class inheriting from abstract class class Sachin(Friends): # Implementing abstract method def role(self): print('Python Developer') # Concrete derived class inheriting from abstract class class Rishu(Friends): # Implementing abstract method def role(self): print('C++ Developer') # Concrete derived class inheriting from abstract class class Yashwant(Friends): # Implementing abstract method def role(self): print('C++ Developer') # Instantiating concrete derived class roles = Sachin() roles.role() # Instantiating concrete derived class roles = Rishu() roles.role() # Instantiating concrete derived class roles = Yashwant() roles.role() |
In the above code, we created an abstract class called Friends
and defined the abstract method role
within the class using the @abstractmethod
decorator.
Then we created three concrete derived classes, Sachin
, Rishu
, and Yashwant
, that inherits from the class Friends
and implemented the abstract method role
within them.
Then we instantiated the derived classes and called the role
using the instance of the classes to display the result.
1 2 3 |
Python Developer C++ Developer C++ Developer |
As we discussed earlier, abstract classes provide a blueprint for implementing methods into concrete subclasses.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
from abc import ABC, abstractmethod class Details(ABC): @abstractmethod def getname(self): return self.name @abstractmethod def getrole(self): return self.role @abstractmethod def gethobby(self): return self.hobby class Sachin(Details): def __init__(self, name="Sachin"): self.name = name self.role = "Python Dev" self.hobby = "Fuseball spielen" def getname(self): return self.name def getrole(self): return self.role def gethobby(self): return self.hobby detail = Sachin() print(detail.getname()) print(detail.getrole()) print(detail.gethobby()) |
In the above code, we created a blueprint for the class Details
. Then we created a class called Sachin
that inherits from Details
, and we implemented the methods according to the blueprint.
Then we instantiated the class Sachin
and then printed the values of getname
, getrole
and gethobby
.
1 2 3 |
Sachin Python Dev Fuseball spielen |
What if we create a class that doesn’t follow the abstract class blueprint?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
from abc import ABC, abstractmethod class Details(ABC): @abstractmethod def getname(self): return self.name @abstractmethod def getrole(self): return self.role @abstractmethod def gethobby(self): return self.hobby class Sachin(Details): def __init__(self, name="Sachin"): self.name = name self.role = "Python Dev" self.hobby = "Fuseball spielen" def getname(self): return self.name def getrole(self): return self.role detail = Sachin() print(detail.getname()) print(detail.getrole()) |
Python will raise an error upon executing the above code because the class Sachin
doesn’t follow the class Details
blueprint.
1 2 3 |
Traceback (most recent call last): .... TypeError: Can't instantiate abstract class Sachin with abstract method gethobby |
Use of ABC
As we saw in the above example that if a derived class doesn’t follow the blueprint of the abstract class, then the error will be raised.
That’s where ABC(Abstract Base Class) plays an important role in making sure that the subclasses must follow that blueprint. Thus we can say that the subclasses inherited from the abstract class must follow the same structure and implements the abstract methods.
Concrete methods inside ABC
We can also define concrete methods within the abstract classes. The concrete method is the normal method that has a complete definition.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
from abc import ABC, abstractmethod # Abstract class class Demo(ABC): # Defining a concrete method def concrete_method(self): print("Calling concrete method") @abstractmethod def data(self): pass # Derived class class Test(Demo): def data(self): pass # Instantiating the class data = Test() # Calling the concrete method data.concrete_method() |
In the above code, concrete_method
is a concrete method defined within the abstract class and the method was invoked using the instance of the class Test
.
1 |
Calling concrete method |
Abstract class instantiation
An abstract class can only be defined but cannot be instantiated because of the fact that they are not a concrete class. Python doesn’t allow creating objects for abstract classes because there is no actual implementation to invoke rather they require subclasses for implementation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
from abc import ABC, abstractmethod class Details(ABC): @abstractmethod def getname(self): return self.name @abstractmethod def getrole(self): return self.role class Sachin(Details): def __init__(self, name="Sachin"): self.name = name self.role = "Python Dev" def getname(self): return self.name def getrole(self): return self.role # Instantiating the abstract class abstract_class = Details() |
Output
1 2 3 |
Traceback (most recent call last): .... TypeError: Can't instantiate abstract class Details with abstract methods getname, getrole |
We got the error stating that we cannot instantiate the abstract class Details
with abstract methods called getname
and getrole
.
Abstract property
Just as the abc
module allows us to define abstract methods using the @abstractmethod
decorator, it also allows us to define abstract properties using the @abstractproperty
decorator.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
from abc import ABC, abstractproperty # Abstract class class Hero(ABC): @abstractproperty def hero_name(self): return self.hname @abstractproperty def reel_name(self): return self.rname # Derived class class RDJ(Hero): def __init__(self): self.hname = "IronMan" self.rname = "Tony Stark" @property def hero_name(self): return self.hname @property def reel_name(self): return self.rname data = RDJ() print(f'The hero name is: {data.hero_name}') print(f'The reel name is: {data.reel_name}') |
We created an abstract class Hero
and defined two abstract properties called hero_name
and reel_name
using @abstractproperty
. Then, within the derived class RDJ
, we used the @property
decorator to implement them that will make them a getter method.
Then we instantiated the class RDJ
and used the class instance to access the values of hero_name
and reel_name
.
1 2 |
The hero name is: IronMan The reel name is: Tony Stark |
If we had not placed the @property
decorator inside the class RDJ
, we would have had to call the hero_name
and reel_name
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
from abc import ABC, abstractproperty # Abstract class class Hero(ABC): @abstractproperty def hero_name(self): return self.hname @abstractproperty def reel_name(self): return self.rname # Derived class class RDJ(Hero): def __init__(self): self.hname = "IronMan" self.rname = "Tony Stark" def hero_name(self): return self.hname def reel_name(self): return self.rname data = RDJ() print(f'The hero name is: {data.hero_name()}') print(f'The reel name is: {data.reel_name()}') ---------- The hero name is: IronMan The reel name is: Tony Stark |
Note: abstractproperty
is a deprecated class, instead we can use @property
with @abstractmethod
to define an abstract property. Pycharm IDE gives a warning upon using the abstractproperty class.
The above code will look like the following if we modify it.
1 2 3 4 5 6 7 8 9 10 11 |
# Abstract class class Hero(ABC): @property @abstractmethod def hero_name(self): return self.hname @property @abstractmethod def reel_name(self): return self.rname |
Just apply the modifications as shown in the above code within the abstract class and run the code. The code will run without any error as earlier.
Conclusion
We’ve covered the fundamentals of abstract classes, abstract methods, and abstract properties in this article. Python has an abc
module that provides infrastructure for defining abstract base classes.
The ABC
class from the abc
module can be used to create an abstract class. ABC
is a helper class that has ABCMeta
as its metaclass, and we can also define abstract classes by passing the metaclass
keyword and using ABCMeta
. The only difference between the two classes is that ABCMeta
has additional functionality.
After creating the abstract class, we used the @abstractmethod
and (@property
with @abstractmethod
) decorators to define the abstract methods and abstract properties within the class.
To understand the theory, we’ve coded the examples alongside the explanation.
πOther articles you might be interested in if you liked this one
β What are class inheritance and different types of inheritance in Python?
β Learn the use cases of the super() function in Python classes.
β How underscores modify accessing the attributes and methods in Python.
β What are __init__ and __call__ in Python.
β Implement a custom deep learning model into the Flask app for image recognition.
β Train a custom deep learning model using the transfer learning technique.
β How to augment data using the existing data in Python.
That’s all for now
Keep Codingββ