BlogsDope image BlogsDope

Abstraction in Python

Dec. 30, 2020 PYTHON 171

Do you like coffee?

I think you do. So how we make coffee?

  1.  Pour milk into the container 
  2.  Mix coffee and sugar   
  3. Drink the coffee   

Wouldn't it be easier if someone else can make it for us? So let us buy an espresso machine and by pushing a button, we get our coffee. But how we are getting the coffee by pushing the button, we do not care because we are getting our coffee. The same happens in programming if there are steps we need to repeat multiple times then we create a function for that. 

However, Just like an espresso machine, we want users to have information about what the object does instead of how it does it. For this to happen we have a concept of Abstraction in Python.   

Abstraction is hiding the implementation and only showing the features we want.

An abstract class is a class having an abstract method. An abstract method is just like any other method but it is just declared in that class without any body. For example,

def any_abstract_method():
    pass

It's body is defined differently for the different subclasses extending the abstract class.

So, we create common methods for subclasses and their implementation is different for different subclasses that means the user is unaware of the basic implementation of the function property.

Let us consider espresso machines as an abstract class because we do not know what is happening inside and our make_coffee is an abstract method, but for make_coffee method (to make coffee) everyone will use different ingredients like Nescafé, Lavazza, caribou coffee, etc.

Thus, if we have an abstract method then it will only have the method signatures it will not have anybody. Simply you could say it would have the parameters but no implementation.

​We can't create an object of the abstract class but can do it for the subclass.

How to Implement Abstraction in Python


  • Python3
from abc import ABC, abstractmethod
class Fees(ABC):
    def print_slip(self,amount):
        print("Fees submitted : ",amount)
    @abstractmethod
    def fees(self,amount):
        pass
   

class Class10(Fees):
    def fees(self,amount):
        print("Total Fees of Class 10th: ",amount)

class Class12(Fees):
    def fees(self,amount):
        print("Total Fees of Class 12th:",amount)
    


obj = Class10()
obj.fees(20000)
obj.print_slip(20000)
obj = Class12()
obj.fees(50000)
obj.print_slip(50000)
Let us check out what this code is all about.
Python has its own module for the base of the Abstract class known as ABC (Abstract Base class).
  • Python3
from abc import ABC , abstractmethod
Sometimes we only want to declare the method without its implementation so we declare the method as abstract to do it and the subclasses can have their own implementation of these methods. So we imported ABC and abstractmethod from the module abc.
​Keep in mind that ABC and abc are different. If you interchange both you will get syntax errors.
Let try create a subclass of ABC because we know we can't create the object of the abstract class. 
syntax : Class SubClassname(SuperClassname)
  • Python3
class Fees(ABC):
    def print_slip(self, amount):
        print("Fees submitted : ",amount)
    @abstractmethod
    def fees(self,amount):
        pass

In class Fees, we have created two functions one is a normal function and the other is an abstract method. For the abstract method, the subclasses of Fees will have their own functionalities. 

So to try our concept, we create two different subclasses of the Fees class to have their own functionalities for the abstract method. 

  • Python3
class Class10(Fees):
    def fees(self, amount):
        print("Total Fees of Class 10th: ",amount)

class Class12(Fees):
    def fees(self,amount):
        print("Total Fees of Class 12th:",amount)

Here we have created two subclasses Class10 and Class12. Both the classes have fees methods but with their own functionality. 

So let us check what happens if we create objects of both classes and call the fees method as well as what happens if we call the normal function (print_slip) from the object of the subclasses.

  • Python3
obj = Class10()
obj.fees(20000)
obj.print_slip(20000)
obj = Class12()
obj.fees(50000)
obj.print_slip(50000)
What we did, we created the object of both classes and called the same function for different objects. 
Now we will see that both statements will show different output.

Output:

Total Fees of Class 10th: 20000 
Fees submitted : 20000 
Total Fees of Class 12th: 50000 
Fees submitted : 50000

What is a Static Method? 

Static methods are those that you can call without creating an object of the class.​​​​​​​ You use a static method when you do not want to use class variables.

What if you want to make your abstract method as Static? 

It's easy when you want to combine two decorators. You mention the decorators here we want to combine static and abstract together. So we will write it like this.

  • Python3
from abc import ABC, abstractmethod 
class Fees(ABC):
    def print_slip(self, amount):
        print("Fees submitted : ",amount)
    @staticmethod
    @abstractmethod
    def fees(amount):
        pass
   

class Class10(Fees):
    @staticmethod
    def fees(amount):
        print("Total Fees of Class 10th: ",amount)

class Class12(Fees):
    @staticmethod
    def fees(amount):
        print("Total Fees of Class 12th:",amount)
        
Class10.fees(2000)
Class12.fees(2000)

Output:

Total Fees of Class 10th: 2000 
Total Fees of Class 12th: 2000

@abstractmethod comes last in the row when you write a combination of decorators otherwise it will give error.

However, there is another way where we can combine the decorators together in a single line or write it as a single decorator example @abstractstaticmethod, @abstractclassmethod, @abstractproperty, etc.

  • Python3
from abc import ABC, abstractstaticmethod
class Fees(ABC):
    def print_slip(self, amount):
        print("Fees submitted : ",amount)
    
    @abstractstaticmethod
    def fees(amount):
        pass
   

class Class10(Fees):
    @staticmethod
    def fees(amount):
        print("Total Fees of Class 10th: ",amount)

class Class12(Fees):
    @staticmethod
    def fees(amount):
        print("Total Fees of Class 12th:",amount)
    
Class10.fees(2000)
Class12.fees(2000)

We made a simple change instead of writing two decorators we wrote it as a single decorator (@abstractstaticmethod).

Remember when you create an abstract static method then in the subclass, you define the method as static. 

You might have noticed that we have removed the self-parameter as well because of that without creating the instance of the class, we can call the method.

Output:

Total Fees of Class 10th: 2000 
Total Fees of Class 12th: 2000

Remember : @abstractstaticmethod,@abstractclassmethod and @abstractproperty decorators have been deprecated since python3.3 so you should not use them. Instead of these you can use the combination of decorators as we have seen above. 

What is class method?

The class method does need any instance it works on the class scope. As in normal methods, we pass the instance as the first argument but in the class method, we pass the class as the first argument. Class methods can also change the state of the class. 

We can also combine abstract method and class methods by mentioning it as @abstractclassmethod. 

  • Python3
from abc import ABC, abstractclassmethod
class Fees(ABC):
    def print_slip(self,amount):
        print("Fees submitted : ",amount)
    
    @abstractclassmethod
    def Fees(cls,amount):
        pass
   

class Class10(Fees):
    @classmethod
    def fees(cls,amount):
        print("Total Fees of Class 10th: ",amount)

class Class12(Fees):
    @classmethod
    def fees(cls,amount):
        print("Total Fees of Class 12th:",amount)
    
Class10.fees(2000)
Class12.fees(2000)

Output:

Total Fees of Class 10th: 2000 
Total Fees of Class 12th: 2000

What is @property decorator?

The property decorator makes the method access as an attribute rather than calling it with “()” .

We can use both the @abstractmethod and @property together by using @abstractproperty 

  • Python3
from abc import ABC, abstractproperty
class Fees(ABC):
    @abstractproperty
    def classname(self):
        pass
   

class Class10(Fees):
    @property
    def classname(self):
        print("I am in class 10")


print(Class10.classname)
Class10().classname

Output

​​<property object at 0x000001C448EAF400> 
I am in class 10
Hope you understand abstraction and its implementation in Python.

Liked the post?
Editor's Picks
0 COMMENT

Please login to view or add comment(s).