Переопределение метода в Python — просто на примерах

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

Содержание

Как переопределить метод в Python?

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

Давайте рассмотрим пример, чтобы лучше понять переопределение методов в Python.

  • Сначала определите класс Employee:
class Employee:
    def __init__(self, name, base_pay):
        self.name = name
        self.base_pay = base_pay

    def get_pay(self):
        return self.base_pay

Класс Employee имеет две переменные экземпляра: name и base_pay. Он также имеет метод get_pay(), который возвращает значение base_pay.

  • Во-вторых, определите SalesEmployee, который наследуется от класса Employee:
class SalesEmployee(Employee):
    def __init__(self, name, base_pay, sales_incentive):
        self.name = name
        self.base_pay = base_pay
        self.sales_incentive = sales_incentive

Класс SalesEmployee имеет три атрибута экземпляра: name, base_pay и sales_incentive.

  • В-третьих, создайте новый экземпляр класса SalesEmployee и отобразите оплату:
john = SalesEmployee('John', 5000, 1500)
print(john.get_pay())

Выход:

5000

Метод get_pay() возвращает только base_pay, а не сумму base_pay и sales_incentive.

Когда вы вызываете get_pay() из экземпляра класса SalesEmployee, Python выполняет метод get_pay() класса Employee, который возвращает значение base_pay.

Чтобы включить стимулирование продаж в оплату, вам необходимо переопределить метод get_pay() в классе SalesEmployee следующим образом:

class SalesEmployee(Employee):
    def __init__(self, name, base_pay, sales_incentive):
        self.name = name
        self.base_pay = base_pay
        self.sales_incentive = sales_incentive

    def get_pay(self):
        return self.base_pay + self.sales_incentive

В этом случае мы говорим, что метод get_pay() в классе SalesEmployee переопределяет метод get_pay() в классе Employee.

Когда вы вызываете метод get_pay() объекта SalesEmployee, Python вызывает метод get_pay() в классе SalesEmployee:

john = SalesEmployee('John', 5000, 1500)
print(john.get_pay())

Выход:

6500

Если вы создадите экземпляр класса Employee, Python вызовет метод get_pay() класса Employee, а не метод get_pay() класса SalesEmployee. Например:

jane = Employee('Jane', 5000)
print(jane.get_pay())

Положил все это вместе.

class Employee:
    def __init__(self, name, base_pay):
        self.name = name
        self.base_pay = base_pay

    def get_pay(self):
        return self.base_pay


class SalesEmployee(Employee):
    def __init__(self, name, base_pay, sales_incentive):
        self.name = name
        self.base_pay = base_pay
        self.sales_incentive = sales_incentive

    def get_pay(self):
        return self.base_pay + self.sales_incentive


if __name__ == '__main__':
    john = SalesEmployee('John', 5000, 1500)
    print(john.get_pay())

    jane = Employee('Jane', 5000)
    print(jane.get_pay())

Пример переопределения расширенного метода

Следующий код определяет класс Parser:

class Parser:
    def __init__(self, text):
        self.text = text

    def email(self):
        match = re.search(r'[a-z0-9\.\-+_]+@[a-z0-9\.\-+_]+\.[a-z]+', self.text)
        if match:
            return match.group(0)
        return None

    def phone(self):
        match = re.search(r'\d{3}-\d{3}-\d{4}', self.text)
        if match:
            return match.group(0)
        return None

    def parse(self):
        return {
            'email': self.email(),
            'phone': self.phone()
        }

Класс Parser имеет атрибут text, который определяет фрагмент текста для анализа. Также класс Parser имеет три метода:

  • Метод email() анализирует текст и возвращает электронное письмо.
  • Метод phone() анализирует текст и возвращает номер телефона в формате nnn-nnnn-nnnn, где n — число от 0 до 9, например 408-205-5663.
  • Метод parse() возвращает словарь, содержащий два элемента: электронная почта и телефон. Он вызывает методы email() и phone() для извлечения адреса электронной почты и телефона из текстового атрибута.

Следующий пример использует класс Parser для извлечения электронной почты и телефона:

s = 'Contact us via 408-205-5663 or [email protected]'
parser = Parser(s)
print(parser.parse())

Выход:

{'email': '[email protected]', 'phone': '408-205-5663'}

Предположим, вам нужно извлечь телефонные номера в формате n-nnn-nnn-nnnn, который является форматом телефонных номеров в Великобритании. Кроме того, вы хотите использовать извлечение электронной почты, например класс Parser.

Для этого вы можете определить новый класс под названием UkParser, который наследуется от класса Parser. В классе UkParser вы переопределяете метод phone() следующим образом:

class UkParser(Parser):
    def phone(self):
        match = re.search(r'(\+\d{1}-\d{3}-\d{3}-\d{4})', self.text)
        if match:
            return match.group(0)
        return None

Следующие примеры используют класс UkParser для извлечения номера телефона (в британском формате) и адреса электронной почты из текста:

s2 = 'Contact me via +1-650-453-3456 or [email protected]'
parser = UkParser(s2)
print(parser.parse())

Выход:

{'email': '[email protected]', 'phone': '+1-650-453-3456'}

В этом примере анализатор вызывает метод parse() из родительского класса, которым является класс Parser. В свою очередь, метод parse() вызывает методы email() и phone().

Однако parser() вызывает не метод phone() класса Parser, а метод phone() класса UkParser:

parser.parse()

Причина в том, что внутри метода parse() self является анализатором, который является экземпляром класса UkParser.

Поэтому, когда вы вызываете метод self.phone() внутри метода parse(), Python будет искать метод phone(), привязанный к экземпляру UkParser.

Положил все это вместе.

import re


class Parser:
    def __init__(self, text):
        self.text = text

    def email(self):
        match = re.search(r'[a-z0-9\.\-+_]+@[a-z0-9\.\-+_]+\.[a-z]+', self.text)
        if match:
            return match.group(0)
        return None

    def phone(self):
        match = re.search(r'\d{3}-\d{3}-\d{4}', self.text)
        if match:
            return match.group(0)
        return None

    def parse(self):
        return {
            'email': self.email(),
            'phone': self.phone()
        }


class UkParser(Parser):
    def phone(self):
        match = re.search(r'(\+\d{1}-\d{3}-\d{3}-\d{4})', self.text)
        if match:
            return match.group(0)
        return None


if __name__ == '__main__':
    s = 'Contact us via 408-205-5663 or [email protected]'
    parser = Parser(s)
    print(parser.parse())

    s2 = 'Contact me via +1-650-453-3456 or [email protected]'
    parser = UkParser(s2)
    print(parser.parse())

Переопределение атрибутов

Ниже показано, как реализовать классы Parser и UkParser путем переопределения атрибутов:

import re


class Parser:
    phone_pattern = r'\d{3}-\d{3}-\d{4}'

    def __init__(self, text):
        self.text = text

    def email(self):
        match = re.search(r'[a-z0-9\.\-+_]+@[a-z0-9\.\-+_]+\.[a-z]+', self.text)
        if match:
            return match.group(0)
        return None

    def phone(self):
        match = re.search(self.phone_pattern, self.text)
        if match:
            return match.group(0)
        return None

    def parse(self):
        return {
            'email': self.email(),
            'phone': self.phone()
        }


class UkParser(Parser):
    phone_pattern = r'(\+\d{1}-\d{3}-\d{3}-\d{4})'


if __name__ == '__main__':
    s = 'Contact us via 408-205-5663 or [email protected]'
    parser = Parser(s)
    print(parser.parse())

    s2 = 'Contact me via +1-650-453-3456 or [email protected]'
    parser = UkParser(s2)
    print(parser.parse())

В этом примере парсер имеет переменную класса phone_pattern. Метод phone() в классе Parser использует шаблон phone_pattern для извлечения номера телефона. Дочерний класс UkParser переопределяет атрибут класса phone_pattern.

Если вы вызываете метод parse() из экземпляра UkParser, метод parse() вызывает метод phone(), который использует шаблон phone_pattern, определенный в классе UkParser.

Похожие посты
Добавить комментарий

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