Полиморфизм в Python

Содержание
Введение
Пример
Duck Typing
Далее по теме

Введение

Попытаюсь разобраться, что подразумевают под полиморфизмом в Python.

Пока что примеры, которые я видел это либо обычное наследование, либо попытка притянуть за уши так называемый Duck Typing, где просто создаются два идентичных по сути объекта, но с разным содержимым в print() и потом радостно заявляется, что можно вызывать одинаковые методы если они есть.

Видимо, вся эта тема нужна тем, кто переходит на Python с других языков программирования, в которых какие-то другие концепции при наследовании.

Полиморфизм означает, что разные объекты могут реагировать на один и тот же вызов функции или метода по-своему.

Простыми словами: два объекта могут иметь метод с одинаковым названием, который делает что-то разное но при это можно спокойно использовать этот метод не заботясь о том какой-именно объект доступен.

class Dog: def speak(self): return "Woof!" class Cat: def speak(self): return "Meow!" def animal_sound(animal): print(animal.speak()) dog = Dog() cat = Cat() animal_sound(dog) # Woof! animal_sound(cat) # Meow!

И у собаки, и у кошки есть метод speak().

Метод animal_sound() не учитывает тип объекта.

Он просто вызывает animal.speak(), и каждый объект реагирует по-своему.

Пример

from abc import abstractmethod class Shape: @abstractmethod def area(self): pass class Circle(Shape): def __init__(self, radius): self.radius = radius def area(self): return 3.1415 * self.radius ** 2 class Square(Shape): def __init__(self, side): self.side = side def area(self): return self.side ** 2 class Triangle(Shape): def __init__(self, base, height): self.base = base self.height = height def area(self): return self.base * self.height * 0.5 shapes = [Circle(4), Square(5), Triangle(6, 7)] for shape in shapes: print(shape.area())

python polymorphism_ex.py

50.264 25 21.0

Теперь создадим новый класс, который не наследует от Shape, не имеет своего метода area() и попробуем применить этот метод к нему.

# Создадим новый класс, не связанный с Shape class Pizza: def __init__(self, topping, radius): self.topping = topping self.radius = radius # Добавим пиццу в формы и посмотрим что будет с площадью shapes = [Circle(4), Square(5), Triangle(6, 7), Pizza("hawaii", 20)] for shape in shapes: print(shape.area())

50.264 25 21.0 Traceback (most recent call last): File "C:\Users\Andrei\polymorphism.py", line 45, in <module> print(shape.area()) AttributeError: 'Pizza' object has no attribute 'area'

Как и следовало ожидать - получили исключение

Если класс Pizza будет наследовать от Circle, у которого есть метод area() то ошибки не будет.

# Переделаем класс Pizza так, чтобы он наследовал от Circle class Pizza(Circle): def __init__(self, topping, radius): super().__init__(radius) self.topping = topping shapes = [Circle(4), Square(5), Triangle(6, 7), Pizza("hawaii", 20)] for shape in shapes: print(shape.area())

50.264 25 21.0 1256.6000000000001

Duck Typing

Лучшее объяснение, которое мне удалось найти заключается в том, что Python не делает явную проверку типа при работе с объектами.

class Duck: def quack(self): print('Quack, quack') def fly(self): print('Flap, Flap!') class Person: def quack(self): print("I'm Quacking Like a Duck!") def fly(self): print("I'm Flapping my Arms!") def quack_and_fly(thing): # Not Duck-Typed (Non-Pythonic) if isinstance(thing, Duck): thing.quack() thing.fly() else: print('This has to be a Duck!') d = Duck() quack_and_fly(d) p = Person() quack_and_fly(p)

Quack, quack Flap, Flap! This has to be a Duck!

В Python нормальным считается такой вариант

def quack_and_fly(thing): thing.quack() thing.fly() d = Duck() quack_and_fly(d) p = Person() quack_and_fly(p)

Quack, quack Flap, Flap! I'm Quacking Like a Duck! I'm Flapping my Arms!

Заметим что нигде нет явной проверки на наличие нужных методом. Если метода нет - будет исключение, это часть философии EAFP - Проще извиниться чем спросить разрешение которой придерживается Python.

Автор статьи: Андрей Олегович

Похожие статьи
ООП в Python
Классы
Методы
class variables
class methods
Статические методы
Наследование
super()
Специальные методы
dataclass
__slots__
Декоратор property
Полиморфизм

Поиск по сайту

Подпишитесь на Telegram канал @aofeed чтобы следить за выходом новых статей и обновлением старых

Перейти на канал

@aofeed

Задать вопрос в Телеграм-группе

@aofeedchat

Контакты и сотрудничество:
Рекомендую наш хостинг beget.ru
Пишите на info@urn.su если Вы:
1. Хотите написать статью для нашего сайта или перевести статью на свой родной язык.
2. Хотите разместить на сайте рекламу, подходящую по тематике.
3. Реклама на моём сайте имеет максимальный уровень цензуры. Если Вы увидели рекламный блок недопустимый для просмотра детьми школьного возраста, вызывающий шок или вводящий в заблуждение - пожалуйста свяжитесь с нами по электронной почте
4. Нашли на сайте ошибку, неточности, баг и т.д. ... .......
5. Статьи можно расшарить в соцсетях, нажав на иконку сети: