- Полиморфизм в Python
- Что такое полиморфизм?
- Пример 1: полиморфизм оператора сложения
- Полиморфизм функций
- Пример 2: полиморфизм на примере функции len()
- Полиморфизм в классах
- Пример 3: полиморфизм в методах класса
- Полиморфизм и наследование
- Пример 4: переопределение метода
- Полиморфизм в «Пайтон»
- Полиморфизм в ООП — что это?
- Пример № 1
- Пример № 2
- Пример № 3
- Пример № 4
Полиморфизм в 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())
Здесь мы можем увидеть, что различные типы данных, такие как строка, список, кортеж, множество и словарь могут работать с функцией 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) — создание методов с одним и тем же именем, но с разными типами аргументов не поддерживается в питоне.
Полиморфизм в «Пайтон»
Полиморфизм — важный принцип объектно-ориентированного программирования. Его знание часто требуют на технических собеседованиях, причем соискателя всегда могут спросить как про полиморфизм в общих чертах, так и про его специфику в контексте разработки на определенном языке (речь идет о полиморфизме в Java, «Питоне» и т. п.). В этой статье мы подробно остановимся на полиморфизме в Python, а также рассмотрим реализацию данного принципа ООП на различных примерах.
Полиморфизм в ООП — что это?
Если говорить буквально, то слово polymorphism означает «множество форм».
То есть один и тот же человек может принимать много форм по аналогии изменения ролей актера в театре. Так и код в программировании — благодаря использованию вышеупомянутого принципа ООП, код становится более гибким, ведь на практике разработчик получает возможность использовать одну и ту же сущность (method, оператор либо объект) для представления разных типов в разных сценариях.
Пример № 1
Хорошо известно, что оператор “+” нередко применяют в программах, написанных на Python. Но использовать этот оператор можно по-разному.
Если мы говорим о целочисленных типах данных, то мы применяем “+” в целях сложения операндов:
number1 = 1 number2 = 2 print(number1 + number2)
Такая программа выведет на экран цифру 3. Элементарно, Ватсон!
Однако применять “+” можно и для конкатенации строк:
string1 = "Hello," string2 = "Otus!" print(string1+" "+string2)
Результат очевиден и здесь:
Какой же вывод можно сделать из вышесказанного? У нас существует единственный оператор “+”, который способен выполнять разные операции для разных типов данных. Это является одним из наиболее простых примеров полиморфизма на «Пайтон».
Пример № 2
В языке Python существуют функции, способные принимать аргументы различных типов. Пример такой функции — len() . Она способна принимать разные типы данных. Работает это следующим образом:
print(len("ООП-программирование")) print(len(["Python", "Java", "C#", "Scala", "C++"])) print(len())
Вывод будет необычен, но если разобраться, то все просто:
Причина в том, что функция len() может работать с разными типами данных: строкой, списком, кортежем, множеством, словарем. В результате в нашем случае одна и та же функция каждый раз возвратила специфичную информацию для каждого типа данных:
- посчитала количество букв в слове «Программирование»;
- посчитала количество слов в списке;
- посчитала количество ключей в словаре.
Пример № 3
Так как различные классы в «Питоне» способны иметь методы с одинаковым именем, то идея вполне подходит и для методов базового класса. Позже мы обобщим вызов данных методов и проигнорируем объект, с которым работаем.
Ниже — пример такого полиморфизма в методах класса:
Мяу! Я кот. Меня зовут Васька. Мне 2 года. Мяу! Гав! Я собака. Меня зовут Мухтар. Мне 3 года. Гав!
У нас создано 2 класса: Cat и Dog. У этих классов структура похожа, плюс они имеют методы с одинаковыми именами:
Но стоит отметить, что нам не пришлось создавать общий класс-родитель, как и не пришлось соединять эти классы вместе каким-нибудь иным методом. Для обоих случаев у нас используется общая переменная animal , что стало возможным благодаря наличию полиморфизма.
Пример № 4
Как и в прочих языках программирования, в «Питоне» классы-потомки способны выполнять наследование методов и атрибутов родительского класса. То есть у нас существует возможность переопределить ряд methods и attributes, сделав это для того, чтобы они соответствовали классу-потомку. Данное поведение называют переопределением (overriding). И благодаря наличию полиморфизма мы можем получать доступ к переопределенным methods и attributes, имеющим такое же имя, как и в parent class.
Пример такого переопределения ниже:
from math import pi class Shape: def __init__(self, name): self.name = name def area(self): pass def fact(self): return "Я - двумерная фигура" def __str__(self): return self.name class Square(Shape): def __init__(self, length): super().__init__("Квадрат") self.length = length def area(self): return self.length**2 def fact(self): return "Любой угол квадрата равен 90 градусов." class Circle(Shape): def __init__(self, radius): super().__init__("Круг") self.radius = radius def area(self): return pi*self.radius**2 a = Square(5) b = Circle(8) print(b) print(b.fact()) print(a.fact()) print(b.area())
Смотрим на вывод программы:
Круг Я - двумерная фигура Любой угол квадрата равняется 90 градусам. 201.06192982974676
В работе кода мы использовали методы __str__() — они не были переопределены в дочерних классах и применяются непосредственно из класса-родителя. То есть интерпретатор «Пайтона» автоматически распознал, что метод fact() для объекта a (class Square) является переопределенным. В результате применяется тот метод, который был определен в классе-потомке.
В это же самое время, метод fact() для объекта b переопределенным не является, в результате чего применяется метод с таким же именем из parent class (Shape).
Важно отметить, что в «Питоне» не поддерживается такой вариант method overriding, как создание методов с тем же самым именем, однако с различными типами аргументов.
Надеемся, теперь вы знаете достаточно, чтобы пройти собеседование. Если же интересуют подробности полиморфизма в Java, можете почитать, к примеру, эту статью. Если же хотите освоить какой-нибудь из вышеупомянутых языков программирования на профессиональном уровне, добро пожаловать на курсы в Otus!