Python Abstract Property
- Python Abstract Property
-
Example: Calling the
mileage
Method of theBike
Class -
Example: Multiple
@abstractmethod
on Different Classes -
Example: Using the
Register()
Method - Conclusion
This tutorial will discuss using the abc
or abstract base classes module to create classes with abstract properties in Python.
Python Abstract Property
Abstraction in object-oriented programming is used to hide unnecessary information from users. The inner workings of a function will be hidden from the user, but the user can use the function to perform a task.
For example, we use computer software to perform different tasks, but we don’t know how the software performs the task. We only give inputs to the software and get outputs from it.
We can use abstraction in Python to reduce the complexity of a program by hiding irrelevant information.
A class will become abstract if it contains one or more abstract methods. Abstract methods are defined in a subclass, and the abstract class will be inherited from the subclass because abstract classes are blueprints of other classes.
In Python, we can use the abc
module or abstract base classes module to implement abstract classes. The abstract base class provides an interface for subclasses, and it is beneficial when the code is large and remembering all the classes is challenging.
We need to import the abc
module in the base class and use it to decorate the base class method as an abstract. To define an abstract method, we can use the @abstractmethod
decorator before defining the method in the base class, and we can use the @property
decorator to make a method an abstract property.
For example, let’s import the abc
module and create a Bike
class that will be inherited from the ABC
class. Inside the Bike
class, we will create an abstract method, mileage()
.
We can now inherit the base class to implement different subclasses with abstract methods. See the code below.
# Class Code
from abc import ABC, abstractmethod
class Bike(ABC):
@property
@abstractmethod
def mileage(self):
pass
class Honda(Bike):
def mileage(self):
print("The mileage is 20kmph")
class CD70(Bike):
def mileage(self):
print("The mileage is 15kmph ")
class CD150(Bike):
def mileage(self):
print("The mileage is 34kmph ")
# Main Code
h = Honda()
h.mileage()
r = CD70()
r.mileage()
s = CD150()
s.mileage()
The code above defines a set of classes related to different types of bikes, including an abstract base class Bike
with an abstract property mileage
. Three concrete classes, Honda
, CD70
, and CD150
, inherit from Bike
and provide their own implementations of the mileage
property.
The Bike
class is an abstract base class (ABC) that inherits from ABC
(Abstract Base Class) and declares an abstract property mileage
using the @property
and @abstractmethod
decorators.
The Honda
, CD70
, and CD150
classes inherit from the Bike
abstract class.
The mileage
method is called on each instance to print the specific mileage information for each type of bike.
Output:
The mileage is 20kmph
The mileage is 15kmph
The mileage is 34kmph
In the above code, we created objects of the subclasses, and then we called their method mileage()
, which will print the mileage of the bike.
Example: Calling the mileage
Method of the Bike
Class
The Bike
class also has the mileage()
method, but we cannot call it because the method is abstract.
For example, let’s repeat the above example and call the mileage
method of the Bike
class. See the code below.
# Class Code
from abc import ABC, abstractmethod
class Bike(ABC):
@property
@abstractmethod
def mileage(self):
pass
class Honda(Bike):
def mileage(self):
print("The mileage is 20kmph")
class CD70(Bike):
def mileage(self):
print("The mileage is 15kmph ")
class CD150(Bike):
def mileage(self):
print("The mileage is 34kmph ")
# Main Code
b = Bike()
b.mileage()
The code defines an abstract base class (Bike
) with an abstract property mileage
. Three concrete subclasses (Honda
, CD70
, and CD150
) inherit from Bike
and provide specific implementations of the mileage
property.
However, in the main code, an attempt is made to instantiate the abstract class Bike
and call its mileage
method, which results in an error (TypeError
).
Output:
TypeError: Can't instantiate abstract class Bike with abstract methods mileage
The above code clearly says that the abstract class Bike
has abstract methods, which is why its object cannot be created and its methods cannot be called.
Example: Multiple @abstractmethod
on Different Classes
We can also make methods of other classes as abstract methods using the @abstractmethod
decorator before the definition of the first method. When one tries to make an object of that class to access the methods, Python will give an error.
For example, let’s make the methods of a subclass abstract. See the code below.
# Class Code
from abc import ABC, abstractmethod
class Bike(ABC):
@property
@abstractmethod
def mileage(self):
pass
class Honda(Bike):
@abstractmethod
def mileage(self):
print("The mileage is 20kmph")
def mileage2(self):
print("The mileage is 200 kmph")
# Main Code
b = Honda()
b.mileage2()
In the code snippet above, Honda
is a concrete class that inherits from Bike
.
It provides a specific implementation of the mileage
property using the @abstractmethod
decorator.
Additionally, it has a non-abstract method (mileage2
) that prints a different mileage value. The error occurs because Honda
is still considered an abstract class due to the presence of the abstract property mileage
declared in the base class Bike
.
Since the mileage
property in Bike
is abstract and does not have a concrete implementation in Honda
, attempting to instantiate Honda
directly results in a TypeError
.
Output:
TypeError: Can't instantiate abstract class Honda with abstract methods mileage
We have defined two methods in the Honda
class, but none of them is accessible because the class is abstract. Check this link for more details about the abstract base classes.
Example: Using the Register()
Method
The register()
method in Python’s abc
module is a mechanism that allows a class to be recognized as a virtual subclass of an abstract base class (ABC) without explicitly inheriting from it.
This method is useful when you have an existing class that you want to designate as a subclass of an abstract class, even if it doesn’t inherit from it in the traditional sense.
See the code below.
from abc import ABC, abstractmethod
class Bike(ABC):
@property
@abstractmethod
def mileage(self):
pass
class Honda:
@property
def mileage(self):
return "The mileage is 20kmph"
# Registering Honda as a virtual subclass of Bike
Bike.register(Honda)
# Instantiate Honda
b = Honda()
# Accessing the abstract property
print(b.mileage)
In this example, Honda
is registered as a virtual subclass of Bike
. The mileage
property is then accessible on an instance of Honda
, even though Honda
does not explicitly inherit from Bike
.
Also, the Honda
class is now marked as a property using the @property
decorator. When you access b.mileage
, it correctly prints The mileage is 20kmph
without raising an AttributeError
.
Output:
The mileage is 20kmph
Now that we added the return
statement in the mileage
method of the Honda
class, the property should correctly return the specified string and expect to see The mileage is 20kmph
in the result.
Conclusion
This tutorial introduces Python abstract properties using the abc
module.
Abstract properties and classes are used to achieve abstraction in object-oriented programming, hiding unnecessary details from users.
The tutorial covers the implementation of abstract properties, creating abstract base classes, and providing concrete implementations in subclasses. It emphasizes the use of the @abstractmethod
decorator and the @property
decorator to define abstract methods and properties.
The tutorial also explores scenarios where abstract classes cannot be instantiated directly and introduces the register()
method for designating virtual subclasses.
Code examples illustrate the concepts, providing a comprehensive understanding of abstract properties in Python.