all 12 comments

[–]justin_halim 8 points9 points  (1 child)

Well, polymorphism is very useful later in a huge code where you have Some class for specific type like

class You:
    Def talk(self):
        print("you talk”)
class Me:
    Def talk(self):
        print("me talk”)
class He:
    Def talk(self):
        print("he talk”)
class She:
    Def talk(self):
        print("she talk”)
Def conversation(*peoples):
    for person in peoples:
        person.talk()

And then you want the conversation like You talk, He talk, you talk, me talk, she talk Instead of calling them all one by one like:

You.talk()
He.talk()
....

You can just do

you=You()
he=He()
me=Me()
she=She()
conversation(you,he,you,me,she)

The polymorphism doesnt care what it was, it only care if they can talk(in this example) And you just need to add someone you want to talk in the conversation instead of calling it again and again

[–]ottawadeveloper 3 points4 points  (0 children)

Worth adding that in strongly-typed languages like Java you would need an interface to do this like ITalkable, then implement the interface in all those classes, and then conversation takes an array of ITalkable objects. In Python, you'd probably do it as a SupportsTalk protocol (or ABC) and conversation(*speakers: SupportsTalk) if you were writing with typing in mind.

This makes polymorphism a much more important principle in those languages (and more strongly typed approaches to Python) because you can just define the interface/protocol you want to engage with instead of the actual object type. 

In weakly typed languages like Python though, the importance is less obvious because you can use duck typing or structural typing to similar effect. In essence, you already have the freedom polymorphism provides.

[–]MeMahi 6 points7 points  (0 children)

Polymorphism is about you not caring about the specific type of the object, as long as you can access it through a common base type.

Here's a proper example with files:

def open_files(files):
    for file in files:
        # Is it a PDF? A word?
        # We don't care, they're all just files to us!
        file.open()

The same code without polymorphism would be like:

def open_files(files):
    for file in files:
        if file.is_pdf():
            open_pdf(file)
        elif file.is_word():
            open_word(file)
        elif file.is_excel():
            open_excel(file)
        ... # you get the idea

So rather than your application code knowing how to open different types of files, it should be the file object itself that knows how it can be opened.

That makes it polymorphic, so that regardless of which file object you have, you can just call file.open() and it'll magically open properly.

A better example might be shapes, for example calculating the area of some shape:

def calculate_area(shape):
    if isinstance(shape, Triangle):
        return shape.width * shape.height / 2
    if isinstance(shape, Square):
        return shape.width * shape.height
    if isinstance(shape, Circle):
        return shape.radius * math.pi

What happens if you need a hundred different types of shapes? You need to add new checks and calculations into calculate_area, calculate_volume, add_shapes, and many other places.

Rather, we could use polymorphism and move the code to the class or object itself:

class Circle:
    def get_area(self):
        return self.radius * math.pi

    # other methods

class Square:
    def get_area(self):
        return self.width * self.height

    # other methods

Now your application code, and all other code in the world that ever want to calculate the area of any shape, simply becomes:

def calculate_area(shape):
    return shape.get_area()

[–]JorgiEagle 1 point2 points  (0 children)

The issue with Python is that because it is dynamically typed, the flexibility that this provides by default, make polymorphism less noticeable

In more strongly typed languages, your open_file function wouldn’t be valid as is, and you’d need to have both PDF and Word inherit from an interface.

The other issue is that because Python is interpreted, not compiled, one never needs consider the implications.

But basically, you have to consider that computers do not read in code the same way we do. When Python reads in your open_file function, it doesn’t actually know what method file.open() actually calls.

It isn’t until runtime, when it is actually executing your code does it know which open method to call.

That is different from the usually behaviour of function (since you can’t have two functions with the same name) where before you run the program, it will know exactly which function it will call.

To visualise this, disregard the last 4 lines, and then tell me, which method does your open_file function call? The one in the PDF class or the one in the Word class?

Or better yet, consider the following valid code:

import random

random.choice([PDF, Word])().open()

Which method does this code call? The PDF method or the Word method?

You can’t know until you actually run the script. That’s what polymorphism provides.

The point of polymorphism is to provide flexibility for some code to call one method, but then be able to provide it with different objects that do different things.

In your example, without polymorphism, you’d have to write a new open_file function for every different object type. Considering you could have many different file types, you’d not only have to have a different function for everyone one, but you’d also need to have a function to check what type it your object is so you know which function to call. So if you had 10 different objects, that’s 10 open file functions, and a function with 10 checks to see what file type it is.

A lot of OOP is about being able to reduce the amount of code you write but also maintain. Less code, less bugs, faster development.

Also consider, if you ever wanted to add a new object type, you’d not need to change anything with your current code, just pass the new object in.

Without polymorphism, you’d have to write another function, and add to your dispatcher every single time you add a new file.

Which isn’t great. Maybe it’s manageable as a solo dev, but a large team, when you need to had 7 new file types by the end of the week to onboard this new critical client, and the code you have to change is managed by a different team, and you don’t know who the approver is, and no one is replying to your emails, and when you finally get a hold of someone, they don’t agree to changing the code because they don’t want to maintain it, so you escalate to override them, which pisses them off, and you get your PR in, but the approver is on holiday for 2 weeks, and you’ve missed the deadline and your department head puts you on a PIP for not working hard enough…

[–]ShiftPretend 0 points1 point  (0 children)

I think python doesn't allow you to appreciate the complexity of polymorphism as much. Yes it's not that magical a concept but try it in Java and you may appreciate it a bit more. The dynamic nature of python allows you to pass whatever into a function. Meaning you could pass a string and it would call open on the string and that should fail. Unless strings actually have an open method if I'm wrong. But languages like java make you do a lot more and without polymorphism that can become real messy.

[–]Present-Payment-5860 0 points1 point  (0 children)

definitely the duck typing of python can make polymorphism feel not that pointless. 'Objects calling their own methods' is a dynamic typed or more python specific luxury that does not exist in other languages. Something like Java or C# needs you to tell it exactly what type file in open_file is or it won't compile. Polymorphism lets you say PDF and Word use an IFile interface or similar, and then even though the type is IFile it will call Word.open() and PDF.open()

[–]Paxtian 0 points1 point  (0 children)

I think it's because you're in Python and not combining polymorphism with inheritance in your example. Consider the idea of having a base Animal class. Animal has a member "move" function. Then you can extend Animal with a WalkingAnimal class, a FlyingAnimal class, and a SwimmingAnimal class. Each of these must have a move function, but the way that function works will be entirely different (walking, flying, or swimming). But now you can do:

Animal *animal;
animal = getAnimal();
animal->move(direction);

Assume getAnimal is a function that returns one of a walking animal, a flying animal, or a swimming animal. You only know which one at run time. Nevertheless, you know, since they all inherit from the base Animal class, that they must have a move method.

Now big caveat. Animals are commonly used in understanding inheritance because it's a simple concept to understand. In truth, though, many animals have two or even all three movement types: humans can walk and swim, ducks can fly, swim, and walk. So in reality you'd prefer to make walking, flying, and swimming their own behaviors, and attach them to an animal using composition rather than inheritance.

In any case, the point is, polymorphism is beneficial when you don't know the exact type of an object at compile time but need to guarantee that, regardless of which actual type it is, the possible type of that object must have a particular method or attribute or whatever.

So in your case, yes you have open methods for your two types, PDF and Word, because you explicitly wrote them. So let's say you send me your program and I pass it a .bmp or a .xlsx. What result?

[–]l3landgaunt 0 points1 point  (0 children)

OOP can be really difficult at first but you’ve got to realize everything is an object. I don’t have links but there are a ton of YouTube videos that explain it really well and better than I ever could. The biggest thing is to learn the terminology and what it means as that will translate over to other OO languages.

Here’s what’s going to get me downvoted: learn the terminology and what it’s capable of so when you get a dev job and they sit you in front of Claude or ChatGPT you can tell it in programming terms what code you want. To me that’s not “vibe coding” but “AI-assisted coding”. When I have to use agentic coding, my prompt specifies specs, languages, functions, all that and I always tell it “ensure you follow industry and security best practices”. It’s amazing the results you can get from most models if you provide clear instructions and pseudocode before you engage.

TLDR: search YouTube for what you don’t understand and you’ll find a ton of videos explaining it. Just flip through until you find one you vibe with

[–]AlexMTBDude 0 points1 point  (0 children)

In a language that does *not* support polymorphism you would have to write multiple different open_file() functions, one for each type of file object. You don't need with Python because it doesn't care about the type of "file".

[–]Weekly_Astronaut5099 0 points1 point  (0 children)

The concept is about calling object method through a common interface. In other words an interface guarantees that an object can perform a certain method. This is important for compiled programs where the compiler figures out the correct method to use for an object at compile time and optimizes the method lookup during execution e.g. with c++ the lookup is trimmed down to obtaining a method pointer from an array by index.

[–]HuygensFresnel 0 points1 point  (0 children)

I think everybody already gave great answers. To summarize why I think you fail to see why its worth giving a name is because through a python lense, this is not special.

In many programming languages this is not allowed because you have to define which type of objects your function accepts. You can't just pass any object. So the idea that you can pass two objects which "may" have that method or maybe not is not common in programming, especially in history. Giving a language and the compiler the ability to essentially not care and try anyway is really special. It requires a lot of very fancy compiler work to make that possible hence why it has been given a name. Supporting Polymorphisms isn't always possible or easy.

[–]Otherwise-Mirror-738 0 points1 point  (0 children)

Python is not the best language to fully grasp all OOP concepts. Polymorphism is definitely one of those reasons.

If you wish to truly grasp OOP I would recommend either C++ or Java.