Что такое полиморфизм в python
Перейти к содержимому

Что такое полиморфизм в python

  • автор:

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

В этой статье мы изучим полиморфизм, разные типы полиморфизма и рассмотрим на примерах как мы можем реализовать полиморфизм в Python.

Что такое полиморфизм?

В буквальном значении полиморфизм означает множество форм.

Полиморфизм — очень важная идея в программировании. Она заключается в использовании единственной сущности(метод, оператор или объект) для представления различных типов в различных сценариях использования.

Давайте посмотрим на пример:

Пример 1: полиморфизм оператора сложения

Мы знаем, что оператор + часто используется в программах на Python. Но он не имеет единственного использования.

Для целочисленного типа данных оператор + используется чтобы сложить операнды.

num1 = 1 num2 = 2 print(num1 + num2)

Итак, программа выведет на экран 3 .

Подобным образом оператор + для строк используется для конкатенации.

str1 = "Python" str2 = "Programming" print(str1+" "+str2)

В результате будет выведено Python Programming .

Здесь мы можем увидеть единственный оператор + выполняющий разные операции для различных типов данных. Это один из самых простых примеров полиморфизма в Python.

Полиморфизм функций

В Python есть некоторые функции, которые могут принимать аргументы разных типов.

Одна из таких функций — len() . Она может принимать различные типы данных. Давайте посмотрим на примере, как это работает.

Пример 2: полиморфизм на примере функции len()

print(len("Programiz")) print(len(["Python", "Java", "C"])) print(len())

Вывод:

9 3 2

Здесь мы можем увидеть, что различные типы данных, такие как строка, список, кортеж, множество и словарь могут работать с функцией len() . Однако, мы можем увидеть, что она возвращает специфичную для каждого типа данных информацию.

Полиморфизм функции len()

Полиморфизм в классах

Полиморфизм — очень важная идея в объектно-ориентированном программировании.

Чтобы узнать больше об ООП в Python, посетите эту статью: Python Object-Oriented Programming.

Мы можем использовать идею полиморфизма для методов класса, так как разные классы в Python могут иметь методы с одинаковым именем.

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

Пример 3: полиморфизм в методах класса

class Cat: def __init__(self, name, age): self.name = name self.age = age def info(self): print(f"I am a cat. My name is . I am years old.") def make_sound(self): print("Meow") class Dog: def __init__(self, name, age): self.name = name self.age = age def info(self): print(f"I am a dog. My name is . I am years old.") def make_sound(self): print("Bark") cat1 = Cat("Kitty", 2.5) dog1 = Dog("Fluffy", 4) for animal in (cat1, dog1): animal.make_sound() animal.info() animal.make_sound()

Вывод:

Meow I am a cat. My name is Kitty. I am 2.5 years old. Meow Bark I am a dog. My name is Fluffy. I am 4 years old. Bark

Здесь мы создали два класса Cat и Dog . У них похожая структура и они имеют методы с одними и теми же именами info() и make_sound() .

Однако, заметьте, что мы не создавали общего класса-родителя и не соединяли классы вместе каким-либо другим способом. Даже если мы можем упаковать два разных объекта в кортеж и итерировать по нему, мы будем использовать общую переменную animal . Это возможно благодаря полиморфизму.

Полиморфизм и наследование

Как и в других языках программирования, в Python дочерние классы могут наследовать методы и атрибуты родительского класса. Мы можем переопределить некоторые методы и атрибуты специально для того, чтобы они соответствовали дочернему классу, и это поведение нам известно как переопределение метода(method overriding).

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

Давайте рассмотрим пример:

Пример 4: переопределение метода

from math import pi class Shape: def __init__(self, name): self.name = name def area(self): pass def fact(self): return "I am a two-dimensional shape." def __str__(self): return self.name class Square(Shape): def __init__(self, length): super().__init__("Square") self.length = length def area(self): return self.length**2 def fact(self): return "Squares have each angle equal to 90 degrees." class Circle(Shape): def __init__(self, radius): super().__init__("Circle") self.radius = radius def area(self): return pi*self.radius**2 a = Square(4) b = Circle(7) print(b) print(b.fact()) print(a.fact()) print(b.area())

Вывод:

Circle I am a two-dimensional shape. Squares have each angle equal to 90 degrees. 153.93804002589985

Здесь мы можем увидеть, что такие методы как __str__() , которые не были переопределены в дочерних классах, используются из родительского класса.

Благодаря полиморфизму интерпретатор питона автоматически распознаёт, что метод fact() для объекта a (класса Square ) переопределён. И использует тот, который определён в дочернем классе.

С другой стороны, так как метод fact() для объекта b не переопределён, то используется метод с таким именем из родительского класса( Shape ).

Полиморфизм на примере дочерних и родительских классов в питоне

Заметьте, что перегрузка методов(method overloading) — создание методов с одним и тем же именем, но с разными типами аргументов не поддерживается в питоне.

Полиморфизм

Полиморфизм (polymorphism) — это понятие из объектно-ориентированного программирования, которое позволяет разным сущностям выполнять одни и те же действия. При этом неважно, как эти сущности устроены внутри и чем они различаются.

С греческого языка слово «полиморфизм» означает «многообразие». Термин используют и в других сферах. Скажем, полиморфизм в биологии — способность какого-то вида существовать в разных формах.

Пример полиформности в природе — пчелы: есть рабочие пчелы, матка, трутни. Они разные, но все могут летать независимо от того, что это за пчела. По похожему принципу работает и полиморфизм в ООП.

Освойте профессию
«Fullstack-разработчик на Python»

Профессия / 12 месяцев
Fullstack-разработчик на Python

Создавайте веб-проекты самостоятельно

dffsdd (3)

Fullstack-разработчик на Python

Fullstack-разработчики могут в одиночку сделать IT-проект от архитектуры до интерфейса. Их навыки востребованы у работодателей, особенно в стартапах. Научитесь программировать на Python и JavaScript и создавайте сервисы с нуля.

картинка - 2023-03-14T190323.524

Например, есть две разных сущности: картинка и видео. И тем, и другим можно поделиться: отправить в личное сообщение другому человеку. Программист может сделать два разных метода — один для картинки, другой для видео. А может воспользоваться полиморфизмом и создать один метод «Отправить» для обеих сущностей.

Такой метод будет называться полиморфным. Плюс этого подхода — разработчик пишет меньше кода и не повторяется.

Чтобы лучше понять, что такое полиморфизм и как он работает, советуем прочитать статью про ООП. Полиморфизм — один из четырех основных принципов этого способа программирования

Для чего нужен полиморфизм

  • Облегчает написание кода. Не нужно придумывать десять разных методов: отправить одно, другое, третье. Есть один метод, который можно применять к разным сущностям и не задумываться.
  • Позволяет масштабировать решения. Если понадобится отправлять не только видео и картинки, но и текст, это можно будет сделать той же командой.
  • Делает код более читаемым. Разработчику не нужно разбираться, что делает десяток методов с похожими названиями. Есть один метод, и по его названию все понятно.
  • Помогает точно понимать, чего ждать от разных методов, то есть делает код более предсказуемым. Не может быть такого, что метод «Отправить» вдруг окажется методом не для картинки, а для видео.

С понятием должен быть знаком любой разработчик. Множество языков программирования используют полиморфизм: C, C++, Java, Python и другие. Не все эти языки чисто объектно-ориентированные: некоторые устроены так, что с ними можно работать в разных парадигмах программирования. Так что столкнуться с полиморфизмом может каждый.

Станьте Fullstack-разработчик на Python и найдите стабильную работу
на удаленке

Полиморфизм как принцип ООП

В объектно-ориентированном программировании четыре основных принципа: инкапсуляция, абстракция, наследование и полиморфизм. Это связанные между собой вещи — без одного не работало бы и другое.

Инкапсуляция — это создание сущностей как «вещей в себе». Классы должны работать независимо друг от друга: если какая-то сущность, например, удалится, это не повлияет на принцип работы остальных.

Абстракция — это принцип, когда какие-то общие вещи сводятся до набора абстрактных признаков. То есть мы имеем не абсолютно разные классы «картинка», «видео», «текст», а абстрактный класс «контент».

Наследование — это возможность делать на основе одних сущностей другие. Обычно в качестве «родителя» используются абстрактные сущности, а от них наследуются уже более конкретные. То есть если родитель — «контент», то дети — «картинка», «видео», «текст». Это все подвиды контента и его наследники.

Чтобы реализовать полиморфизм, нужны как минимум абстракция и наследование. Они помогают сделать абстрактный класс, в нем — абстрактный «общий» метод, а потом унаследовать разные реализации этого метода. В итоге название одно, а механика разная в зависимости от подтипа. Сейчас разберемся подробнее.

Что такое полиморфный метод и как его создают

Полиформный — это многообразный: формы различаются, а действие одно и то же. Тот же самый метод «Отправить» из примера выше может быть реализован по-разному для видео и картинки. Но вызывается он одинаково для всех видов контента и выполняет одну и ту же задачу. Вот как это работает.

Сначала программист создает общий класс. Например, «контент». В нем он описывает вещи, общие для всего контента: свойства и методы. Свойства — это признаки, то, что есть у контента: количество лайков, возможность комментирования и так далее. А методы — это действия, то есть команды: контент можно лайкнуть, открыть на отдельной вкладке, репостнуть или отправить в личное сообщение.

У общего класса — абстрактные, общие методы. Контент можно отправить, но как — пока непонятно. Зато уже можно описать, как будет выглядеть эта команда: как она называется, что в нее нужно передать, какое сообщение выдать после этого. Это своего рода каркас будущего конкретного действия.

Затем разработчик создает производные классы. Это наследники общего класса: они более конкретные, у них могут быть дополнительные свойства и методы. Например, видео можно поставить на паузу, а картинку — нет. А еще у них сохраняются абстрактные свойства и методы родителя: их переопределяют, чтобы они тоже работали конкретнее.

У производных классов — свои реализации общих методов. Например, в классе «контент» есть метод «отправить». Он же есть и в производных классах. В классе «картинка» может быть свой код для отправки, а в классе «видео» — свой. Они могут быть похожи или различаться. Но название у них окажется одинаковым, и делать они будут одно и то же.

Можно создавать объекты производных классов и пользоваться их методами. Абстрактные классы существуют как бы в вакууме: нельзя создать объект, который будет принадлежать такому классу. Среди реальных объектов не может быть «просто контента», который не является ни текстом, ни картинкой, ни видео, ни еще чем-то. Соответственно, абстрактные методы никто не будет вызывать. А вот переопределенные методы из производных классов — вполне реальные, ими можно пользоваться в разных ситуациях.

Формы полиморфизма

Существуют разные виды полиморфизма. Вообще-то классификация довольно широкая и начинающему легко в ней запутаться, поэтому мы решили ограничиться только основными формами.

Полиморфизм подтипов. Это полиморфность «по умолчанию»: когда в ООП говорят о полиморфизме, обычно имеют в виду его. Выше мы рассказывали именно про такой тип. Это возможность использовать одни и те же команды, или интерфейсы, для разных сущностей — подтипов.

Параметрический полиморфизм. Его еще называют обобщенным полиморфизмом. В нем для команды не имеет значения, какую сущность ей прислали: для всех возможных классов будет использоваться один код. Такой полиморфизм считается «истинным» и делает код универсальнее, но реализовать его сложнее.

Полиморфизм ad hoc. Этот вид полиморфизма еще называют специализированным. Его иногда противопоставляют параметрическому: идея ad hoc — разный код при одинаковом названии. Часто такой полиморфизм реализуют с помощью перегрузки методов: несколько раз пишут метод с одним и тем же названием, но разным кодом.

Статический и динамический полиморфизм

На более «глубоком», близком к машине уровне полиморфизм можно разделить на две группы — статический и динамический. Разница —в том, когда программа переходит от общего метода к одной из его вариаций.

  • Статический — метод переопределяют при компиляции.
  • Динамический — при выполнении программы.

Статический полиморфизм реализуют с помощью перегрузки методов, о которой мы рассказывали выше. Динамический — с помощью абстракций. Обычно в объектно-ориентированных языках есть возможность применить оба варианта.

Преимущества полиморфизма

  • Код становится аккуратнее: не приходится множить сущности и создавать десяток команд, которые делают одно и то же. Нет «лапши» — бессвязного неструктурированного кода, в котором тяжело разобраться.
  • Разработчику удобнее: не нужно каждый раз думать, что делает команда «Отправить» для конкретного вида контента, можно просто написать ее и получить результат.
  • Работать с разными сущностями можно одинаково: не обязательно каждый раз узнавать, о каком именно производном классе речь идет на этот раз. Ведь общее полиморфное действие есть для всего.
  • Код легче расширять, использовать заново и всячески модифицировать.

Недостатки полиморфизма

  • Связь полиморфизма с наследованием порой расценивают как слабое место всей концепции. Если нужен полиформный класс, но для конкретной ситуации не подходит наследование, — реализация может усложниться.
  • Не всегда полиморфизм легко реализовать на практике. Поэтому существует довольно много реализаций, которые работают плохо: с багами и необъяснимыми ошибками.
  • Полиморфизм может ухудшать производительность кода, делать его более «тяжелым» и медленным. Но тут многое зависит от реализации: скажем, параметрический обычно быстрее, чем ad hoc.
  • Новичкам бывает тяжело понять принцип — объяснить полиморфизм простыми словами можно только в связке с другими понятиями ООП. Так что человек на момент изучения уже должен понимать, что такое объектно-ориентированное программирование.

Как начать изучать полиморфизм

Мы советуем начать с основ: сначала разобраться, как работает программирование в целом, потом перейти к принципам ООП и полиморфизму. На всех этапах лучше практиковаться, чтобы закреплять знания, — к тому же на реальных примерах легче понять тот или иной концепт.

Вы можете записаться на наши курсы и начать учиться уже сейчас. Обещаем много реальных задач и интересной практики!

Инкапсуляция, наследование, полиморфизм

Python 3 логотип

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

Инкапсуляция

Инкапсуляция — ограничение доступа к составляющим объект компонентам (методам и переменным). Инкапсуляция делает некоторые из компонент доступными только внутри класса.

Инкапсуляция в Python работает лишь на уровне соглашения между программистами о том, какие атрибуты являются общедоступными, а какие — внутренними.

Одиночное подчеркивание в начале имени атрибута говорит о том, что переменная или метод не предназначен для использования вне методов класса, однако атрибут доступен по этому имени.

Двойное подчеркивание в начале имени атрибута даёт большую защиту: атрибут становится недоступным по этому имени.
   File 

Однако полностью это не защищает, так как атрибут всё равно остаётся доступным под именем _ИмяКласса__ИмяАтрибута:

Наследование

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

 
 

Для вставки кода на Python в комментарий заключайте его в теги

  • Модуль csv - чтение и запись CSV файлов
  • Создаём сайт на Django, используя хорошие практики. Часть 1: создаём проект
  • Онлайн-обучение Python: сравнение популярных программ
  • Книги о Python
  • GUI (графический интерфейс пользователя)
  • Курсы Python
  • Модули
  • Новости мира Python
  • NumPy
  • Обработка данных
  • Основы программирования
  • Примеры программ
  • Типы данных в Python
  • Видео
  • Python для Web
  • Работа для Python-программистов
  • Сделай свой вклад в развитие сайта!
  • Самоучитель Python
  • Карта сайта
  • Отзывы на книги по Python
  • Реклама на сайте

Наследование

Наследование — это способность объекта принимать одну или несколько характеристик от других классов объектов, обычно переменных или функций-членов. Можно провести аналогию между этим понятием и наследственностью как передачей характерных черт от родителей к потомству. Например, у ребенка могут быть глаза отца и улыбка матери. Глаза отца и улыбка матери — это черты, которые ребенок наследует от своих родителей. Они выглядят/проявляются одинаково у родителей и потомства.

Информатика использует понятие наследования при создании классов, между которыми устанавливаются отношения “род-вид”. В отношениях “род-вид” один объект связан с другим объектом. Например, собака — это домашнее животное, сельдерей — овощ, а Марс — планета. В отношениях “род-вид” есть две сущности: родитель и ребенок. Родитель в этих отношениях является общей версией ребенка. Собака (ребенок) — это домашнее животное (родитель). В информатике мы называем родительский класс в отношениях “род-вид” “суперклассом”, а дочерний — “подклассом”. Подкласс наследует методы и/или переменные от суперкласса. Теперь напишем код для отношений dog/pet (собака/домашнее животное).

Создание подкласса

class Pet: 
def __init__(self,name=””):
print(“Hi! I’m your new pet! My name is: %s” % name)
self.name = name
def feedme(self):
print(“%s says: I’m hungry! Feed me!” % self.name)
def eat(self,food_name):
print(“%s just ate a %s” %(self.name,food_name))
# Создайте класс Dog, который наследует классу Pet
class Dog(Pet):
def __init__(self,name=””):
print(“Hi! I’m your new dog!”)
self.name = name
# Протестируйте программу
d = dog()
d.feedme()d.eat(“Potato”)

Обратите внимание на то, что в приведенных примерах для создания класса Dog мы заключаем Pet в скобки в объявлении класса: Dog(Pet) . Использование этого синтаксиса позволяет сообщить Python, что класс, который мы создаем, является подклассом суперкласса Pet. Поскольку ни один из методов и переменных в классе Pet не является закрытым, подкласс Dog сможет получить доступ ко всем элементам класса Pet. Именно так экземпляр собаки способен вызывать методы feedme() и eat() .

Некоторые атрибуты класса могут быть созданы закрытыми. Создать переменную закрытой означает, что этот атрибут не будет доступен подклассу. Имейте это в виду при проектировании классов!

Полиморфизм

Теперь, когда вы получили представление о наследовании, можно перейти к понятию “полиморфизм”. Полиморфизм — это способность чего-либо иметь несколько форм. Вернемся к предыдущему примеру. Все домашние животные в конечном итоге нуждаются в еде, но способ, которым они питаются, может отличаться. Например, попугай будет есть, клюя корм для птиц, в то время как собака будет есть, пережевывая собачий корм. И попугай, и собака — домашние животные, которые едят пищу, но разница в том, что они едят разную пищу по-разному. Взглянем на пример в коде.

class Pet: 
def __init__(self,name=””):
self.name = name
def feedme(self):
print(“%s says: I’m hungry! Feed me!” % self.name)
def eat(self,food_name):
print(“%s just ate a %s” %(self.name,food_name))
# Создайте класс Dog, который наследует классу Pet
class Dog(Pet):
def __init__(self,name=””):
print(“Hi! I’m your new dog!”)
self.name = name
def eat(self,food_name):
print(“%s is chewing!” % (self.name))
print(“%s just ate a %s” %(self.name,food_name))
# Создайте класс Parrot, который наследует классу Pet
class Parrot(Pet):
def __init__(self,name=””):
print(“Hi! I’m your new parrot!”)
self.name = name

def eat(self,food_name):
print(“%s is pecking at their food!” % (self.name))
print(“%s just ate a %s” %(self.name,food_name))

В этом примере собака и попугай переопределяют метод eat(self,food_name) . Переопределение метода означает, что метод в подклассе переопределяет метод, указанный в суперклассе. В этом суть полиморфизма: один и тот же метод, но разные характеристики в зависимости от класса.

Заключение

Мы кратко рассмотрели наследование и полиморфизм в Python. Поначалу эти понятия, возможно, будет непросто усвоить. Лучший способ справиться с этим — разработать классы, которые отражают сущности реального мира, а затем идентифицировать свойственные им отношения “род-вид”.

  • 4 совета Python Django разработчику
  • Python Django: контактная форма с автоматической отправкой Email
  • Python для начинающих: какая разница между tuple, list и set?

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *