Python is one of the most popular programming languages due to its versatility and its user-friendly syntax. Like other languages that accommodate object-oriented programming (OOP), Python is polymorphic. This means that a single operator, function, or class method in Python can have multiple uses. These various uses might be challenging to learn, but they ultimately make Python a more efficient language.
Today, we’ll discuss polymorphism and how it works in Python.
We’ll cover the following topics:
Polymorphism is the principle that one kind of thing can take a variety of forms. In the context of programming, this means that a single entity in a programming language can behave in multiple ways depending on the context. It’s similar to how a word like “express” can act as a verb in one sentence, a noun in another sentence, and an adjective in a third sentence. The sequence of letters on the page doesn’t change, but the meaning they add to the sentence is fundamentally different in each case. Likewise, in polymorphic programming languages, a single entity can act differently in different contexts.
Polymorphism is a basic condition of Python, and it affects how the language works at multiple levels. Today, we’ll focus on the polymorphism of operators, functions, and class methods in Python.
Operator polymorphism, or operator overloading, means that one symbol can be used to perform multiple operations. One of the simplest examples of this is the addition operator +
. Python’s addition operator works differently in relation to different data types.
For example, if the +
operates on two integers, the result is additive, returning the sum of the two integers.
int1 = 10int2 = 15print(int1 + int2)# returns 25
In the example above, the +
operator adds 10
and 15
, such that the output is 25
.
However, if the addition operator is used on two strings, it concatenates the strings. Here’s an example of how the +
operator acts on string data types.
str1 = "10"str2 = "15"print(str1 + str2)# returns 1015
In this case, the output is 1015
because the +
operator concatenates the strings “10”
and “15”
. This is one example of how a single operator can perform distinct operations in different contexts.
Certain functions in Python are polymorphic as well, meaning that they can act on multiple data types and structures to yield different kinds of information.
Python’s built-in len()
function, for instance, can be used to return the length of an object. However, it will measure the length of the object differently depending on the object’s data type and structure. For instance, if the object is a string, the len()
function will return the number of characters in the string. If the object is a list, it will return the number of entries in the list.
Here’s an example of how the len()
function acts on strings and lists:
str1 = "animal"print(len(str1))# returns 6list1 = ["giraffe","lion","bear","dog"]print(len(list1))# returns 4
The outputs are 6
and 4
, respectively, because the len()
function counts the number of characters in a string and the number of entries in a list. The function operates differently depending on the nature of the data it’s acting on.
Python’s polymorphic nature makes it easier to repurpose classes and methods. Remember that a class is like a blueprint, and an object is a concrete instantiation of that blueprint. So, a method that is part of a class will reoccur in the objects that instantiate that class. Likewise, if you generate a new class from a preexisting class, the new class will inherit the methods of the preexisting class. The new class in this scenario is called a “child class,” while the preexisting class is called the “parent class.”
Here’s an example of a parent class and a child class that’s derived from it. Note that the parent class establishes the method type
, so the child class inherits that method. The method is redefined in the child class, however, such that objects instantiated from the child class use the redefined method. This is called “method overriding.”
# Define parent class Animalclass Animal:# Define methoddef type(self):print("animal")# Define child class Dogclass Dog (Animal):def type(self):print("dog")# Initialize objectsobj_bear = Animal()obj_terrier = Dog()obj_bear.type()# returns animalobj_terrier.type()# returns dog
The method name type
remains the same in the child class, but it has been overridden. An object instantiated from the parent class will use the original method as it is defined in the parent class, while a method instantiated from the child class will use the overridden method. Therefore, the outputs from the program above are animal
and dog
, respectively.
A similar principle applies to classes that are independent of each other. For instance, imagine that you’re creating two new classes: Lion
and Giraffe
.
class Lion:def diet(self):print(“carnivore”)class Giraffe:def diet(self):print(“herbivore”)obj_lion=Lion()obj_giraffe=Giraffe()obj_lion.diet()# returns carnivoreobj_giraffe.diet()# returns herbivore
The outputs from this program are carnivore
and herbivore
, respectively. The two classes both use the method name diet
, but they define those methods differently. An object instantiated from the Lion
class will use the method as it is defined in that class. The Giraffe
class may have a method with the same name, but objects instantiated from the Lion
class won’t interact with it.
Try one of our 300+ courses and learning paths: Python for Programmers.
The best way to learn a new coding skill is by actually practicing it. Try running the code in the examples below to see polymorphism in action!
First, let’s practice operator polymorphism. We’ll use the +
operator to add the integers 2
and 3
while concatenating the strings “2”
and “3”
.
int1 = 2int2 = 3print(int1+int2)str1 = "2"str2 = "3"print(str1+str2)
Next, try using the len()
function to measure the length of the string “numbers”
and the list [“1”,“2”,“3”,“4”]
.
str1="numbers"print(len(str1))list1=["1","2","3","4"]print(len(list1))
Class method polymorphism is a little more complicated. In the code block below, we’ve created a parent class Fish
and defined a class method type
. We’ve then created a child class called Shark
while overriding the type
method so that objects instantiated from the Shark
class use the overridden method.
class Fish:def type(self):print("fish")class Shark(Fish):def type(self):print("shark")obj_goldfish=Fish()obj_hammerhead=Shark()obj_goldfish.type()obj_hammerhead.type()
Finally, below, we’ve created two new, independent classes: Turtle
and Frog
. When you instantiate an object from the Turtle
class, the object will use the type
method as it is defined in that class. The same will be true of objects instantiated from the Frog
class, despite the fact that the methods have the same name.
class Turtle:def type(self):print("turtle")class Frog:def type(self):print("frog")obj_sea_turtle=Turtle()obj_treefrog=Frog()obj_sea_turtle.type()obj_treefrog.type()
Polymorphism is an important element of object-oriented programming in Python. Polymorphism makes Python a more versatile and efficient language. It allows you to use a single operator or function to perform multiple tasks. It also allows you to reuse method names while redefining them for the unique purposes of different classes.
Learning how to make use of the polymorphism of operators, functions, and class methods might be challenging, but once you’ve done so, you’ll be a more adept programmer.
To learn more about using Python, consider exploring Educative’s Python for Programmers learning path. Over the course of four modules, you’ll learn the fundamentals of Python and then gradually progress to more advanced skills. If you’re already familiar with Python and are preparing for an interview, consider the Ace the Python Coding Interview learning path. It will help you brush up on your Python skills while also giving you opportunities to practice real interview questions.
Happy learning!
Free Resources