How To Use Polymorphism In Python?

Published On: Wed, 31 Jul 2024 Updated On: Wed, 31 Jul 2024

Polymorphism in Python: The OOP Concept

Polymorphism means "One with multiple forms". It is one of the key features of object-oriented programming(OOP). It empowers developers to write flexible and adaptable code and allows different objects to respond to the same function or method in distinct ways therefore promoting code reusability and modularity. This article will walk through the concept of polymorphism in Python. You will understand its significance in OOP, polymorphic functions, method overloading, and how inheritance and interfaces enable polymorphic behaviour. Through practical examples, you will witness the true power and versatility of polymorphism in Python.

Understanding the Polymorphism

Imagine you are visiting a grocery store to buy several grocery items. The shop has a shopkeeper who finds and gives the requested item(s). Each time you request him for some item, he will bring the item and hand it over to you. Here, you need to understand that shop is a complete application and the shopkeeper is the single function that serves you to get the items you want based on what data you pass to the shopkeeper() function. You can not deny the below possibilities:

1. Asking the shopkeeper for each item one by one. See the below sample code.

Code Example
inventory = [
    'apple',
    'oranges',
    'pineapple',
    'avocado',
    'grapes',
    'mango',
    ...
]

def shopkeeper(item):
    if item in inventory:
        return item
    
    return f'{item} - Not available'

print(shopkeeper('grapes'))
print(shopkeeper('potatos'))

# Output
# grapes
# potatos - Not available

2. Ask the shopkeeper to give all items at once. See the code below.

Code Example
inventory = [
    'apple',
    'oranges',
    'pineapple',
    'avocado',
    'grapes',
    'mango',
    ...
]

def shopkeeper(items):
    result = []
    for item in items:
        if item in inventory:
            result.append(item)
        else:
            result.append(f'{item} - Not available')
    
    return result

print(shopkeeper(['grapes', 'potatos', 'oranges']))

As you can understand the shopkeeper assumes the role of multiple nature of work. He can facilitate a single item as well as multiple items based on the request. This is the concept of polymorphism where one function/object changes its behaviour based on the nature of work.

Significance of Polymorphism in OOP

You might know the trigonometry terminology to denote multi-angle shapes. We have different words such as Triangle, Rectangle, Pentagon, Hexagon etc. To denote all these at once we commonly use "Polygon"  meaning the shape has many angles. Below is the Google screenshot for reference of where this "polygon" came from.

https://www.google.com/search?q=polygon+etymology&sca_esv=ce82090d53e0c143&rlz=1C1VDKB_enIN1090IN1090&sxsrf=ADLYWIJ5_ff6JF_wTwtOMca-fLfIJqVwCw%3A1722427025909&ei=kSaqZtmaN6PuseMPudbw4QM&ved=0ahUKEwiZp5_YnNGHAxUjd2wGHTkrPDwQ4dUDCBA&uact=5&oq=polygon+etymology&gs_lp=Egxnd3Mtd2l6LXNlcnAiEXBvbHlnb24gZXR5bW9sb2d5MgsQABiABBiRAhiKBTIGEAAYFhgeMgYQABgWGB4yCBAAGBYYHhgPMggQABgWGB4YDzIIEAAYFhgeGA8yCxAAGIAEGIYDGIoFMgsQABiABBiGAxiKBTIIEAAYgAQYogRIgyRQighY8RRwAngBkAEAmAHAAaAByQuqAQMwLjm4AQPIAQD4AQGYAgugAvwLwgIHECMYsAMYJ8ICChAAGLADGNYEGEfCAg0QABiABBiwAxhDGIoFwgIREAAYgAQYkQIYsQMYgwEYigXCAgUQABiABMICBxAAGIAEGArCAggQABgWGAoYHpgDAIgGAZAGCpIHAzIuOaAH3Tc&sclient=gws-wiz-serp
The "Polygon" Origin

The "Polymorphism" word also comes from the Greek words "poly," meaning "many," and "morph," meaning "form". Therefore, we can understand the word "Polymorphic" as "The one who has many shapes" and "Polymorphism" as the "ability to take multiple forms".

So, do you think the shopkeeper() function is polymorphic? If you differ, please comment.

In our shopkeeper example, you must have seen that two functions operate on different data types that are string and list.

In the context of OOP, the concept of polymorphism allows a single function or method to operate on different data types or classes seamlessly. It weaponizes developers to write code that can handle diverse data without knowing the specific types at compile time. Let's combine both examples for different possibilities below:

Code Example
inventory = [
    'apple',
    'oranges',
    'pineapple',
    'avocado',
    'grapes',
    'mango',
    ...
]

def shopkeeper(item):
    if isinstance(item, str):     # Check if the shopkeeper function is given "string" parameter
        if item in inventory:
            return item
        else:
            return f'{item} - Not available'
    elif isinstance(item, list):  # Check if the shopkeeper function is given "list" parameter
        result = []
        for i in item:
            if i in inventory:
                result.append(i)
            else:
                result.append(f'{i} - Not available')
        return result
    else:
        raise TypeError("Invalid input type")

# Now you can pass either single item or all items to shopkeeper()
print("Ask shopkeeper to give items one by one")
print(shopkeeper('grapes'))
print(shopkeeper('potatos'))
print("Ask shopkeeper to give all items at once")
print(shopkeeper(['grapes', 'potatos', 'oranges']))

Polymorphism promotes the concept of reusability and Do Not Repeat(DRY), making it tremendously easier to maintain and extend applications. Developers can create more flexible and robust software solutions by designing classes and functions with polymorphic capabilities.

Polymorphic Functions and Method Overloading

shopkeeper() is a polymorphic function. Let's take another example so that it becomes more clear to you. Consider a simple addition function:

Code Example
 
Code Example
def add(a, b):
    return a + b

This add function can handle various data types, such as integers, floats, and concatenate strings.

Code Example
 
Code Example
print(add(2, 3))       # Output: 5
print(add(3.14, 2.86)) # Output: 6.0
print(add("Hello, ", "World!"))  # Output: "Hello, World!"

Method overloading is another way to achieve polymorphism within classes. It allows a class to have multiple methods with the same name but different parameters. Being a dynamic typing language, Python does not natively support method overloading, but we can achieve it through default parameter values or using the *args and **kwargs techniques. See the below example that demonstrates that the second method overwrites the previous method definition even if we pass different data types.

Code Example
class Calculator:
    def add(self, a:int, b:int):
        print("I am adding numeric values")
        return a + b

    def add(self, a:str, b:str):
        print("I am concatanating string values")
        return a + b
    
calc = Calculator()
print(calc.add(2, 3))
print(calc.add("Smiaansh", "Technologies"))

Method Overriding

Polymorphism becomes potent when combined with inheritance. Subclasses can override methods from their superclass(s), providing their implementation while maintaining the same method name. It allows different classes to exhibit polymorphic behaviour while adhering to a standard interface.

Code Example
class Shape:
    def area(self):
        pass  # Abstract method

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 3.14 * self.radius ** 2

In this example, Shape is the superclass, while Rectangle and Circle are subclasses. Both subclasses override the area() method to calculate their specific area formulas.

Practical Examples of Polymorphism in Python

Polymorphism is evident in many built-in Python functions, such as len(), str(), and sum(). These functions can work with various data types, adjusting their behaviour accordingly.

Code Example
print(len([1, 2, 3]))        # Output: 3
print(len("Hello, World!"))  # Output: 13
print(str(123))              # Output: "123"
print(str(3.14))             # Output: "3.14"
print(sum([1, 2, 3]))        # Output: 6
print(sum((1, 2, 3)))        # Output: 6

Conclusion

Code Example
 

Polymorphism is a powerful concept in Python that enhances the flexibility and adaptability of object-oriented programs. Polymorphism promotes code reuse and modularity by allowing functions and methods to operate on different data types and classes. From polymorphic functions and method overloading to leveraging inheritance and interfaces for polymorphic behaviour, Python empowers developers to write versatile and scalable applications. Embrace the essence of polymorphism and elevate your Python programming to new heights of efficiency and elegance.

How To Use Polymorphism In Python?

Reader Comments


Add a Comment