Документация по Python

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

В: Документация по Python

Основной полиморфизм

Полиморфизм - это способность выполнять действие над объектом независимо от его типа. Это обычно реализуется путем создания базового класса и наличия двух или более подклассов, которые все реализуют методы с одинаковой сигнатурой. Любая другая функция или метод, который манипулирует этими объектами, может вызывать одни и те же методы независимо от того, с каким типом объекта он работает, без предварительной проверки типа. В объектно-ориентированной терминологии, когда класс X расширяет класс Y, Y называется суперклассом или базовым классом, а X называется подклассом или производным классом.

class Shape:
    """Это родительский класс, который предназначен для наследования другими классами."""
    
    def calculate_area(self):
        
        """Этот метод предназначен для переопределения в подклассах.
         Если подкласс не реализует его, но вызывается, будет поднят NotImplemented."""
         
        #raise NotImplementedError("Not implemented")   
        
class Square(Shape):
    """Это подкласс класса Shape, представляющий собой квадрат."""

    side_length = 2     # в этом примере стороны имеют длину 2 единицы
    
    def calculate_area(self):
        """Этот метод переопределяет Shape.calculate_area(). 
       Когда у объекта типа Square есть свой метод calculate_area(),
       это метод, который будет вызываться, а не версия родительского класса.
       Он выполняет расчет, необходимый для этой формы, квадрата и возвращает результат."""
        
        return self.side_length * 2
    
class Triangle(Shape):
    """Это также подкласс класса Shape, и он представляет собой треугольник."""
    base_length = 4
    height = 3
        
    def calculate_area(self):
        """Этот метод также переопределяет Shape.calculate_area() и выполняет вычисление площади.
         расчет для треугольника, возвращающий результат."""

        return 0.5 * self.base_length * self.height

def get_area(input_obj):
    """
     Эта функция принимает входной объект и вызывает функцию этого объекта.
     метод calculate_area(). Обратите внимание, что тип объекта не указан. Это
     может быть объектом Square, Triangle или Shape.
     """

    print(input_obj.calculate_area())

# Создадим по одному объекту каждого класса
shape_obj = Shape()
square_obj = Square()
triangle_obj = Triangle()

# Теперь передайте каждый объект по одному функции get_area() и посмотрите результат.

get_area(shape_obj)
get_area(square_obj)
get_area(triangle_obj)

Мы должны увидеть этот вывод:

None
4
6.0

Что происходит без полиморфизма?   Без полиморфизма может потребоваться проверка типа перед выполнением действия над объектом, чтобы определить правильный метод для вызова. Следующий пример счетчика выполняет ту же задачу, что и предыдущий код, но без использования полиморфизма, то get_area() функция должна делать больше работы.

class Square:

    side_length = 2

    def calculate_square_area(self):
        return self.side_length ** 2

class Triangle:

    base_length = 4
    height = 3

    def calculate_triangle_area(self):
        return (0.5 * self.base_length) * self.height

def get_area(input_obj):

    # Обратите внимание на проверки типов, которые здесь необходимы. Эти проверки типа
    # может стать очень сложным для более сложного примера, что приведет к
    # дублирующийся и сложный в сопровождении код.
    
    if type(input_obj).__name__ == "Square":
        area = input_obj.calculate_square_area()

    elif type(input_obj).__name__ == "Triangle":
        area = input_obj.calculate_triangle_area()

    print(area)

# Создадим по одному объекту каждого класса
square_obj = Square()
triangle_obj = Triangle()

# Теперь передайте каждый объект, по одному, в функцию get_area() и просмотрите результат.
get_area(square_obj)
get_area(triangle_obj)

Мы должны увидеть этот вывод:

4
6.0

Важная заметка   Обратите внимание, что классы, используемые в примере счетчика, являются классами «нового стиля» и неявно наследуются от класса объекта, если используется Python 3. Полиморфизм будет работать как в Python 2.x, так и в 3.x, но код контрпримера полиморфизма вызовет исключение, если он будет выполнен в интерпретаторе Python 2.x из-за типа (input_obj). имя будет возвращать «экземпляр» вместо имени класса , если они явно не наследуют от объекта, в результате чего в области никогда не быть назначен.

Duck Typing

Полиморфизм без наследования в форме утиной типизации, доступной в Python, благодаря его динамической системе типирования. Это означает, что до тех пор, пока классы содержат одинаковые методы, интерпретатор Python не различает их, поскольку единственная проверка вызовов происходит во время выполнения.

class Duck:
    def quack(self):
        print("Quaaaaaack!")
    def feathers(self):
        print("The duck has white and gray feathers.")

class Person:
    def quack(self):
        print("The person imitates a duck.")
    def feathers(self):
        print("The person takes a feather from the ground and shows it.")
    def name(self):
        print("John Smith")

def in_the_forest(obj):
    obj.quack()
    obj.feathers()

donald = Duck()
john = Person()
in_the_forest(donald)
in_the_forest(john)

Выход:

Quaaaaaack!
The duck has white and gray feathers.
The person imitates a duck.
The person takes a feather from the ground and shows it.
Еще от кодкамп
Замечательно! Вы успешно подписались.
Добро пожаловать обратно! Вы успешно вошли
Вы успешно подписались на кодкамп.
Срок действия вашей ссылки истек.
Ура! Проверьте свою электронную почту на наличие волшебной ссылки для входа.
Успех! Ваша платежная информация обновлена.
Ваша платежная информация не была обновлена.