# Polymorphism in Python Code Examples - Functions, Classes, Inheritance and Duck Typing

By:   |   Updated: 2024-07-19   |   Comments   |   Related: > Python

##### Problem

What is polymorphism and how does Python implement polymorphism, let's check out this tip to learn more.

##### Solution

Polymorphism is a popular term in object-oriented programming (OOP) languages. An object can take multiple forms in different ways in polymorphism. For example, a woman takes different roles in her daily life, such as wife, professional, athlete, mother, and daughter, as the diagram below depicts:

Similarly, Python programming supports polymorphism, where an object takes a different role based on usage and situations. Let's explain this using the addition operator (+) as an example.

The addition operator (+) sums the given number. The below code performs addition on two numbers, x and y.

```x = 5
y = 10
z = x + y
print (z)
```

However, when using the same addition operator, the strings act as a concatenation operator. In the example below, it concatenates two strings, "Hello" and "World!" and prints "Hello World!"

```str1 = "Hello"
str2 = "World!"
print(str1+" "+str2)
```

Like the addition operator (+), you can use the multiply operator (*). It can multiply numbers or be used to duplicate strings n number of times.

The first piece of code performs the multiplication of two numbers, x and y; the other code performs string multiplication (duplicate of strings).

```x = 5
y = 10
print('Multiplication of x and y:', x * y)

n = 3
str = 'MSSQLTips'
print('Multiplication of strings:', n * str)
```

## Function Polymorphism

Python len() function is an example of function polymorphism. The len() function works differently with different types of objects, as shown below.

• For strings, it returns the number of characters. For example, len(mssqltips) returns 9.
• For a list, it counts the number of objects. For example, len([100,'apple','banana',50]) returns an object count of 4.
• For a dictionary, it counts the number of key-value pairs. For example, len({"first_name":"raj","last_name":"gupta"}) returns key-value pair counts as 2.

## Class Polymorphism

We can implement polymorphism in Python through classes as well. Let's clarify it using the example code below.

• It creates two classes, Pomegranates() and Banana(), with function types (), color(), and size() in both classes.
• It creates two objects, obj1 and obj2, from the defined classes.
• The for loop iterates through the objects obj1 and obj2, and it calls the function that belongs to the specific class despite having the same function name defined in each class.
```class Pomegranates():
def type(self):
print("fruit")
def color(self):
print("Red")
def size(self):
print("small, tart fruit")

class Banana():
def type(self):
print("Fruit")
def color(self):
print("Yellow")
def size(self):
print("tropical fruit with soft flesh and a soft yellow rind")

obj1 = Pomegranates()
obj2 = Banana()

for fruit in (obj1, obj2): # creating a loop to iterate through the obj1 and obj2
fruit.type()
fruit.color()
fruit.size()
```

## Polymorphism with Inheritance

In a parent-child class method, the child class inherits the method from the parent class. However, modifying the child class method to override the parent class method is feasible. This is called method overriding.

Let's look at the code example below:

• It creates a parent class, Fruits, with the function intro() and taste().
• It creates two child classes that inherit the parent class method intro() and taste().
• In the child class, we defined another function taste() that overrides the parent class method taste().
```class Fruits:
def intro(self):
print("There are different types of fruits")

def taste(self):
print("fruits taste can be sweet, semi-sweet, acidic, semi-acidic, or neutral")

class Mangoes(Fruits):
def taste(self):
print("mangoes are sweet and juicy with a tropical flavor")

class orange(Fruits):
def taste(self):
print("Oranges have a sweet-tart flavor that's similar to citrus, with hints of bitterness and a balanced taste profile")

```

Now, let's create the objects from the parent and call the methods to print the messages.

```obj_fruit = Fruits()
obj_fruit.intro()
obj_fruit.taste()
```

Similarly, create the child class method and see the method overriding behavior. It prints the messages from the child class as it overrides the taste() method inherited from the parent class.

```obj_m = Mangoes()
obj_m.intro()
obj_m.taste()
```
```obj_o = orange()
obj_o.intro()
obj_o.taste()
```

## Multiple Inheritance

How does inheritance work for a child class with multiple parent classes? For example, the code below contains two parent classes: Person and Company. It declares one child class Employee that inherits methods from both parent classes.

We created an object from the Employee() child class and accessed the parent class functions. It prints the message from the parent classes, as shown below.

```class Person:
def person_info(self, name, age):
print('Name:', name, 'Age:', age)

class Company:
def company_info(self, companyname, type):
print('Name:', companyname, 'type:', type)

class Employee(Person, Company):
pass

emp = Employee()

# access data
emp.person_info('raj', 35)
emp.company_info('mssqltips', 'IT')
```

If you define the same function in the child class, it overrides the parent class behavior. For example, let's create the person_name function in the child class with an additional parameter.

Now, if you call the object person_info function, it requires additional parameter input and prints the message defined in the child class, as shown below.

```class Person:
def person_info(self, name, age):
print('Name:', name, 'Age:', age)

class Company:
def company_info(self, companyname, type):
print('Name:', companyname, 'type:', type)

class Employee(Person, Company):
def person_info(self, name, age,sex):  # Override parent method
print('Employee Name:', name, 'Employee Age:', age,'sex:',sex)

emp = Employee()

# access data
emp.person_info('john',45,'Male')
emp.company_info('mssqltips', 'IT')
```

Without the additional parameter defined in the child class, Python gives the following error:

## Duck Typing in Python

You might have heard a saying, "If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck." The saying means we do not check the object type, but instead check its properties to match the objects. In Python, we do not check the object types; instead, we check the presence of an attribute or method. Let's look at the following example code:

• It creates two classes, Duck and Person.
• Each class has a function quack().
• We do not check the object types in the function animals(forest). It should just have the quack function.
```class Duck:
def quack(self):
print('I am a Duck and I do Quack-Quack!')

class Person:
def quack(self):
print('I am a human and do not do quack like a Duck!')

def animals(forest):
return(forest.quack())

obj1 = Duck()
obj2 = Person()
animals(obj1)
animals(obj2)
```

Let's create another class without the quack function. The Airplane class has a fly function().

```class Duck:
def quack(self):
print('I am a Duck and I do Quack-Quack!')

class Person:
def quack(self):
print('I am a human and do not do quack like a Duck!')

class Airplane:
def fly(self):
print('I fly high in the sky!')

def animals(forest):
return(forest.quack())

obj1 = Duck()
obj2 = Person()
obj3 = Airplane()
animals(obj1)
animals(obj2)
animals(obj3)
```

The Python code output generates an attribute error stating that the 'Airplane' object has no attribute 'quack'.

##### Next Steps
• Stay tuned for more Python tutorials in upcoming tips.
• Explore existing Python tips on MSSQLTips.