Переопределение метода в Python — просто на примерах
В этом руководстве вы узнаете и рассмотрите на примерах, как использовать переопределение метода в 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.