Skip to main content
Home

Main navigation

  • Home
  • Latest Articles

Polymorphism

Breadcrumb

  • Home
  • Polymorphism

Table of Contents

Table of contents
By prateek | Sun December 01, 2024

Understanding the Concept of Polymorphism

Hello people! Let us address polymorphism. Think once more, though, before you think it's restricted to Python or even just programming. One finds this idea all around life. It is the theory that the same object behaves in similar way even if it shows up in numerous forms. Sounds like something I know. Stay here; I will dissect it for you.

Especially in object-oriented programming, polymorphism is like this hidden weapon allowing a particular interface or operation fit many data types in the coding universe. Imagine a classroom or conference when the route of action varies based on the issue to handle different tasks. Here is a straightforward illustration: Imagine a class labeled "Animal" with students designated "Dog" and "Cat." Both of these subclasses borrow from "Animal" and can bark or meow with a technique known as "sound."

class Animal:
   def sound(self):
       pass

class Dog(Animal):
   def sound(self):
       return "Woof!"

class Cat(Animal):
   def sound(self):
       return "Meow!"

Here, then, the "sound" approach is cool. Changing its behavior depending on whether it's with a "Dog" or a "Cat," it is a chameleon. The worst part is that you shouldn't worry about the kind you are dealing with. The approach is the same everywhere thus you may apply it without considering the particular nature of the item too much.

def make_sound(animal):
   print(animal.sound())

dog = Dog()
cat = Cat()

make_sound(dog)  # Outputs: Woof!
make_sound(cat)  # Outputs: Meow!

Go over the code above. See how the "make_ sound" feature rolls? It makes no difference if handling a dog or a cat. It only uses that "sound" approach on every animal that comes upon it. That is polymorphism's magic! Regarding maintenance, it increases the loner-friendliness, simplifies your code, and cranks up the versatility.

Stay with us as we will then be delving into the several kinds of polymorphism Python provides and how you may weave them into your code. You should not miss it!

Types of Polymorphism in Python

Alright, time to explore the several interesting forms of Python's types of polymorphism. Let us deconstruct them:

  • Duck Typing
  • Operator Overloading
  • Method Overloading and Overriding

Duck typing is this odd concept related to dynamic typing whereby the methods an object rolls with take precedence over its class type. You're simply looking for whether an object can accomplish what you need—like having a particular function or attribute—instead of thinking about what kind it is. Examine this sample:

class Duck:
   def quack(self):
       return "Quack!"

class Dog:
   def quack(self):
       return "Dog doesn't quack!"

def make_sound(animal):
   print(animal.quack())

duck = Duck()
dog = Dog()

make_sound(duck)  # Outputs: Quack!
make_sound(dog)  # Outputs: Dog doesn't quack!

Look at that. The make_sound function merely requires knowledge of the quack approach of the object. For you, that is duck typing.

Let us now turn now to operator overloading. This one's about letting operators change their approach based on what they're handling. Therefore, the plus "operator" serves purposes other than only numerical addition. It can even combine lists or thread strings together! The int, str, and list classes help that "+" operator to undergo a makeover.

print(1 + 2)  # Outputs: 3
print("Hello " + "World!")  # Outputs: Hello World!
print([1, 2, 3] + [4, 5, 6])  # Outputs: [1, 2, 3, 4, 5, 6]

We also have method overloading and overriding lastly. Method overloading allows one method to pull off several tricks depending on the count or kinds of its parameters. method overriding? At this point a subclass intervenes and adds spices to a method already in motion in its superclass. Stay tight; in the next sections we will explore these several forms of polymorphism more closely.

Duck Typing and Polymorphism

Let's discuss Duck Typing, a tidy idea in programming intimately related to dynamic typing. Here, the stuff an object can accomplish—its methods and properties—matter more than its class or type. In Python, it's a huge concern when it comes to precisely addressing polymorphism. From the adage "If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck," the odd word "duck typing" results. In Python, then, the type of an object is essentially determined by behavior rather than its family tree.

Need an illustration to understand what I mean? Check this out:

class Duck:
   def fly(self):
       return "Duck flies in the sky!"

class Airplane:
   def fly(self):
       return "Airplane flies in the sky too!"

def lets_fly(flying_object):
   print(flying_object.fly())

duck = Duck()
airplane = Airplane()

lets_fly(duck)  # Outputs: Duck flies in the sky!
lets_fly(airplane)  # Outputs: Airplane flies in the sky too!

See how the function lets_fly doesn't worry over what kind of object it's acquiring in that small code sample above? Just fine as long as the thing can perform a "fly" action. Duck typing is really in action here. Your code will be more laid back and easier to comprehend if you may switch objects around as long as they strut the same stuff. Duck typing, however, allows you, the programmer, the responsibility of ensuring such objects indeed possess the right methods and attributes. You are the one in charge.

Operator Overloading: Polymorphism in Action

Let's explore Python's quite amazing technique of operator overloading—a really cool form of polymorphism. This allows operators to modify their actions depending on the usage of them. Thus, depending on the context, operators like +, -, *, and / could have several meanings. Quite clever, right?

The plus "operator," for instance, typically adds numbers. It may, however, also combine lists or even thread strings together. This occurs because, when handling an int, a str, or a list, the "+" operator operates differently.

print(1 + 2) # Outputs: 3
print("Hello " + "World!")  # Outputs: Hello World!
print([1, 2, 3] + [4, 5, 6])  # Outputs: [1, 2, 3, 4, 5, 6]

The entertaining aspect is You can even have operators work their magic on your own bespoke classes. This means specifying unique methods for your class. Each operator will find particular names for these techniques that fit them. Let's check how it performs with a "Vector" class and how we might spice it with the "+" operator:

class Vector:
   def __init__(self, x, y):
       self.x = x
       self.y = y

   def __add__(self, other):
       return Vector(self.x + other.x, self.y + other.y)

   def __str__(self):
       return f"Vector({self.x}, {self.y})"

v1 = Vector(1, 2)
v2 = Vector(3, 4)

print(v1 + v2)  # Outputs: Vector(4, 6)

In this case, Python generates the "__add__" method behind scenes when you use the "+" operator on two Vector objects. Turning a Vector object into a string with str or just print it straight triggers the "__str__" method.

Operator overloading can help your code seem natural and easy to scan over. Just a heads-up though: even if it's a great tool, you should use it sensibly. Here, misdirection can complicate matters more than it would be useful. Thus, tread carefully!

Method Overloading and Overriding: Examples of Polymorphism

Let us now explore two clever instances of polymorphism with an eye on class methods: method overloading and overriding.

Method overloading is the situation when one method is flexible enough to manage several jobs depending on the quantity or type of their parameters. Now here's a twist: Python does not offer method overloading in the same manner as several other languages. Still, relax! With either variable-length or default arguments, we can create a comparable impact.

Consider this:

def add(a, b, c=0):
   return a + b + c
   
print(add(1, 2))  # Outputs: 3
print(add(1, 2, 3))  # Outputs: 6

See how the "add" function might operate with either two or three inputs in this bit? That's an active type of method overloading!

Method overriding, on the other hand, lets a subclass modify objects using a method already defined in its superclass. When you want a method to run similarly but with a twist in the subclass, it's handy.

Look at this:

class Animal:
   def sound(self):
       return "Animal makes a sound"

class Dog(Animal):
   def sound(self):
       return "Dog barks"

animal = Animal()
dog = Dog()

print(animal.sound())  # Outputs: Animal makes a sound
print(dog.sound())  # Outputs: Dog barks

Here the "Dog" class steps in to offer some original twist by using the "sound" technique recommended in the "Animal" lesson. Your technique is fantastic! Overloading and overriding provide strong tools to keep your code flexible and under control. Just keep in mind to use them properly to keep objects perfect and free of flaws!

Common Mistakes and Best Practices in Implementing Polymorphism

Although Python's incredibly handy tool is polymorphism, you have to be careful how you apply it to prevent certain typical oopsies. Working with polymorphism, here are some best practices and errors to avoid:

  • Make sure your objects have the correct methods and properties double-checked when rolling using duck typing. Should not be the case, you could run across runtime problems. Your friend here is the hasattr function—use it to confirm whether an object packs a certain method or property.
  • Overusing operator overloading: Indeed, operator overloading can help your code seem more natural, but avoid overreaching. Only overload operators if they actually simplify your code and help to clear things out.
  • Not Applying Superclasses: Often it's wise to call the superclass's function with super() when you are overriding methods. This lets you simply change what's required while leaning on the current code.
  • Ignoring the Liskov Substitution Principle: This idea holds that subclasses ought to be able to replace their superclass without causing program problems. Stray from this, and you could find unanticipated problems and behaviors.

Real-world Applications of Polymorphism in Python

A fundamental idea in object-oriented programming, polymorphism finds expression in many practical contexts. Let's explore some instances when it really shines.

  • Graphical user interfaces (GUIs) allow polymorphism to assist control user events such mouse clicks and key presses. Different things may exhibit polymorphism at work and respond differently to the same stimulus.
  • In the realm of game, characters, weapons, and more can all act in unusual ways when interacting with one another. Polymorphism enables the flexible, straightforward handling of these interactions.
  • Web frameworks control HTTP inquiries by means of polymorphism. Depending on who knocks at the door, they can link several paths or URLs to various purposes and call the correct one.
  • In machine learning, several models may have the same interface—that of fit or predict—but they apply these functions in their own distinct ways. This kind of polymorphism allows shifting between models easy.
PreviousNext

Python Syllabus

  • Python Control Flow
    • Python If Statement
    • Python else Statements
    • Python elif Statements
    • Python for Loops
    • Python while Loops
    • Python iterators and iterables
    • Python Comprehensions
    • Conditional List Comprehensions in Python
    • Conditional Dictionary Comprehensions in Python
    • Set Comprehensions in Python
    • Generator Expressions in python
    • Generator Functions in Python
    • Python Yield Statement
  • Functions and Functional Programming
    • Function Syntax in Python
    • Function Parameters in Python
    • Function Arguments in Python
    • Arguments and Return Values
    • Positional Arguments
    • Keyword Arguments
    • Python Default Arguments
    • Returning Values in Python
    • Function Decorators
    • Generator Functions
    • Yield Statement
    • Lambda Functions: Syntax and Usage
    • Lambda with Built-in Functions
    • Functions as First-Class Citizens
    • Passing Functions as Arguments
    • Returning Functions from Functions
  • Python's Object-Oriented Programming
    • Classes and Objects
    • Attributes and Methods
    • Class vs. Instance Attributes
    • Creating Instances in Python
    • Constructors and Initialization in Python
    • Python Destructors
    • Accessing Instance Variables
    • Calling Instance Methods
    • Inheritance and Polymorphism
    • Base and Derived Classes
    • Method Overriding
    • Polymorphism
    • Constructor (__init__)
    • Destructor
    • String Representation
    • Comparison Methods
    • Using Decorators to Modify Classes
  • Exceptions and Error Handling
    • Basic and Custom Exceptions
    • Subclassing Built-in Exceptions
    • Handling Exceptions
    • Multiple except Blocks
    • else and finally Clauses
    • Using else and finally Blocks
    • with Statement
    • Defining __enter__ and __exit__ Methods
    • Using Contextlib for Context Management
  • Python's Standard Library
    • Overview of Key Modules
    • os Module
    • System-specific Parameters and Functions
    • Date and Time Manipulation
    • Random Number Generation
    • Mathematical Functions
    • JSON Data Serialization and Deserialization
    • Regular Expression Operations
    • Additional Data Structures
    • Higher-Order Functions and Operations
    • Object Serialization
  • Python for Web and Internet
    • Python Web Scraping
    • HTML Parsing
    • Navigating the DOM
    • Selenium
    • Web Automation
    • MVC Architecture
    • URL Routing
    • ORM (Object-Relational Mapping)
    • Template Engine
    • Lightweight Web Framework
    • Routing
    • Extensions
    • API Interactions
    • Sending HTTP Requests
    • Authentication
  • Python for Data Science
    • Data Manipulation
    • Data Structures
    • Data Cleaning and Preprocessing
    • Data Manipulation (Filtering, Sorting, Grouping)
    • Arrays and Matrix Operations
    • Mathematical Functions
    • Linear Algebra Operations
    • Data Visualization
    • Basic Plotting
    • Subplots
    • Statistical Visualization
    • Styling and Aesthetics
    • Pair Plots and Heatmaps
    • Statistical Analysis
    • Statistical Functions
    • Probability Distributions
    • Machine Learning
    • Deep Learning Framework
    • Neural Network Building
    • Dynamic Computational Graphs
  • Advanced Python Features
    • asyncio
    • Metaclasses
    • Type Hints
  • Job and Career Opportunities
    • Python and its Relevance in the Job Market
    • Python in Web Development: Career Prospects
    • Python in Back-End Development: Job Opportunities
    • Python in Cloud Computing: Future Scope
    • Python in Network Programming: Career Prospects
    • Python in Data Processing: Career Growth
    • Python in Machine Learning: Job Roles
    • Python in Security Software Development: Career Prospects

Footer menu

  • Contact

Copyright © 2024 GyataAI - All rights reserved

GyataAI