Автор оригинала: Francisco R Porrata.
В этой статье мы собираемся исследовать концепцию переопределения в Python. Мы также собираемся исследовать, какие магические методы и абстрактные классы.
Вступление
Переопределение – это интересная концепция в объектно-ориентированном программировании. Когда метод определения базового класса изменяются в классе подкласса (полученный), это называется переопределением метода. Вы сохраняете одну и ту же подпись метода, но изменяя определение или реализацию метода, определенного одним из предков. Нет специальных синтаксисов или дополнительных ключевых слов, необходимых для проведения метода, перекрывающегося в Python. Это очень важная объектно-ориентированная концепция программирования, так как она делает наследство, используя свою полную мощность. Overriding is an interesting concept in object-oriented programming . When the method definitions of a Base Class are changed in a Subclass (Derived) Class this is called a method override. You are keeping the same signature of the method but changing the definition or implementation of a method defined by one of the ancestors. There is no special syntax or additional keywords needed to do method overriding in Python. It is a very important object-oriented programming concept since it makes inheritance exploit its full power. In essence, you are not duplicating code, thus following the programming principle of DRY (do not repeat yourself), and you can enhance the method in the subclass. По сути, вы не дублируете код, таким образом, следуя принципу программирования сухих (не повторяйте себя), и вы можете улучшить метод в подклассе.
Чтобы понять концепцию переопределения, вы должны знать основные концепции объектно-ориентированного программирования, такие как классы и наследство. В Интернете много ресурсов о ООП. To understand the concept of overrides, you must know the basic concepts of object-oriented programming such as classes and inheritance. There are many resources on the internet about OOP. A really good resource is Finxter Academy’s object-oriented Python class: https://academy.finxter.com/university/object-oriented-python/Действительно хороший ресурс – это ориентированный объектно-ориентированный класс Python Academy Academy:
Нужно для переопределения
В следующем примере вы видите, как работает наследование, и проблема не переопределить метод в подклассе. У материнского класса есть метод WHOAMI
Это отображает «Я родитель»
Отказ In the following example, you see how inheritance works and the problem of not overriding a method in the subclass. The Parent class has a method whoami
that displays "I am a parent"
. This method is inherited by the Child
class. Calling the
Пример наследования без переопределения метода:
class Parent(): def whoami(self): print("I am a parent") class Child(Parent): def play(self): print(" I am playing") child = Child() child.whoami() # Output: # I am a parent
Основное переопределение
Следующий пример показывает, как основные переопределенные работы. В этом примере Ребенок
Класс имеет определение WHOAMI
Метод, который переопределяет метод от Родитель
учебный класс. Призывая WHOAMI
Метод от Ребенок
Класс теперь отображает «Я ребенок»
Отказ
Базовый переопределенный пример:
#Overriding class Parent(): def whoami(self): print("I am a parent") class Child(Parent): def play(self): print(" I am playing") def whoami(self): print("I am a child") parent = Parent() parent.whoami() print() child = Child() child.whoami() # Output: # I am a parent # I am a child
Расширение метода через переопределение
Третий пример показывает, как вы можете простираться Способ в базовом классе путем переопределения метода в подклассе. The third example shows how you can extend
a method in a Base Class by overriding the method in the Subclass. To do that we use the
Сотрудник
Класс имеет следующие данные для сотрудника: номер сотрудника, имя сотрудника, зарплата и, номер отдела. Эта информация передается в экземпляр объекта в __init__
метод. Showemployeree
Способ класса затем отображает эту информацию, отформатированную с помощью новых строк.
Продавец
класс наследует от Сотрудник
учебный класс. По умолчанию он наследует Showemployeree
метод как есть из Сотрудник
учебный класс. Единственная проблема заключается в том, что мы хотим показать комиссию, что продавец получает в рамках печатной информации. Вот где требуется переопределение. Мы хотим повторно использовать Showemployeree
Метод от Сотрудник
учебный класс Но мы хотим продлить его, чтобы добавить информацию комиссии. Это достигается с помощью Super ()
Встроенная функция. В приведенном ниже примере вы видите, что в Продавец
Класс, Super ()
используется дважды. The Salesman
class inherits from the Employee
class. By default, it inherits the showEmployee
method as-is from the Employee
class. The only problem is that we want to display the commission that the salesman receives as part of the printed information. Here is where overriding is needed. We want to reuse the showEmployee
method from the
Третий класс называется Генеральный директор
использует ту же логику, что и раньше. A third class called CEO
uses the same logic as before. The showEmployee
method in this case displays the employee information plus the stock options for the
class Employee(): def __init__(self, empno, ename, salary, deptno): self.Empno = empno self.Ename = ename self.Salary = salary self.Deptno = deptno def showEmployee(self): print("Employee # : {}\nEmployee Name : {}\nSalary : {}\nDepartment : {}".format(self.Empno, self.Ename, self.Salary, self.Deptno)) class Salesman(Employee): def __init__(self, empno, ename, salary, deptno, comm): self.Commission = comm super().__init__(empno, ename, salary, deptno) def showEmployee(self): print("Salesman Profile") super().showEmployee() print("Commision : ", self.Commission) class CEO(Employee): def __init__(self, empno, ename, salary, deptno, stock): self.Stock = stock super().__init__(empno, ename, salary, deptno) def showEmployee(self): print("CEO Profile") super().showEmployee() print("Stock Options : ", self.Stock) salesman = Salesman(200, "John Doe", 67000, "Sales", 100) salesman.showEmployee() print("") ceo = CEO(40, "Jennifer Smith", 300000, "Director", 1000000) ceo.showEmployee()
Выход:
Salesman Profile Employee # : 200 Employee Name : John Doe Salary : 67000 Department : Sales Commision : 100 CEO Profile Employee # : 40 Employee Name : Jennifer Smith Salary : 300000 Department : Director Stock Options : 1000000
Многократное наследование Переопределение
Понимание Многократное наследование имеет свои проблемы. Одним из них является использование Super ()
Отказ Вот ссылка на статью об этом вопросе: https://www.datacamp.com/community/tutorials/super-multiple-ineritance-diamond-problem.
В приведенном ниже примере я хотел показать способ переопределить способ из подкласса с несколькими наследованиями. In the example below, I wanted to show a way to override a method from a subclass with multiple inheritance. The example consists of three classes: Account
, Customer
, and Orders
. Пример состоит из трех классов:
-
Учетная запись
Класс имеет свое имя и номер и метод отображения, который отображает эту информацию. -
Клиент
Класс имеет также свое имя и номер и метод отображения, который отображает эту информацию. -
Заказы
Класс отображает информацию о заказе для клиента на конкретном счете. Он наследует как изУчетная запись
и класс заказов. The
Вот пример:
class Account(): def __init__(self, name, number): self.Name = name self.Number = number def display(self): print("Account # : {}\nAccount Name : {}".format(self.Number, self.Name)) class Customer(): def __init__(self, name, number): self.Name = name self.Number = number def display(self): print("Customer # : {}\nCustomer Name : {}".format(self.Number, self.Name)) class Orders(Account, Customer): def __init__(self, acctnumber, acctname, custnumber, custname, ordnumber, ordnamename, product, qty): self.OrdNumber = ordnumber self.Product = product self.Qty = qty self.OrdName = ordnamename self.acct = Account(acctname, acctnumber) self.cust = Customer(custname, custnumber) def display(self): print("Order Information") self.acct.display() self.cust.display() print("Order # : {}\nOrder Name : {}\nProduct : {}\nQuantiy : {}".format(self.OrdNumber, self.OrdName, self.Product, self.Qty)) acct = Account("AB Enterprise", 12345) acct.display() print("") cust = Customer("John Smith", 45678) cust.display() print("") order = Orders(12345, "AB Enterprise", 45678,"John Smith", 1, "Order 1", "Widget", 5, ) order.display()
Выход:
Account # : 12345 Account Name : AB Enterprise Customer # : 45678 Customer Name : John Smith Order Information Account # : 12345 Account Name : AB Enterprise Customer # : 45678 Customer Name : John Smith Order # : 1 Order Name : Order 1 Product : Widget Quantiy : 5
Различные переопределенные сценарии
1 – Методы класса
Методы классов особенные в том смысле, что они могут быть вызваны в классе самостоятельно или по экземплярам класса. Они связывают с классом, поэтому это означает, что первый аргумент, переданный методу, является классом, а не экземпляром.
Методы классов написаны аналогично методам регулярных экземпляров. Одно отличие – это использование Декоратор @classmethod
Чтобы определить, что метод является методом класса. Также по Конвенции, а не используя себя, чтобы ссылаться на экземпляр класса, CLS
использует для ссылки класса. Class methods are written similarly to regular instance methods. One difference is the use of the
class Account(): @classmethod def getClassVersion(cls): print("Account class version is 1.0")
Для получения дополнительной информации о методах класса проверьте это интернет сайт.
Вот пример проблемы, когда вы столкнетесь при переопределении метода класса:
class ParentClass: @classmethod def display(cls, arg): print("ParentClass") class SubClass(ParentClass): @classmethod def display(cls, arg): ret = ParentClass.create(cls, arg) print("Subclass") return ret SubClass.display("test")
Выход:
create() takes 2 positional arguments but 3 were given
В Подкласс
звонок к Parentclass
Способ создания не является несвязанным вызовом, как это происходит с нормальным методом экземпляра. Итоги этого звонка – это Типеррор Потому что метод получил слишком много аргументов.
Решение для использования Super ()
Для успешного использования родительской реализации.
class ParentClass: @classmethod def display(cls, arg): print("ParentClass") class SubClass(ParentClass): @classmethod def display(cls, arg): ret = super(SubClass, cls).create(arg) print("Subclass") return ret SubClass.display("test")
Выход:
ParentClass Subclass
2 – Магические методы
Что такое магические методы?
Magic Methods – это набор методов, которые Python автоматически связывается с каждым определением класса. Ваши классы могут переопределить эти магические методы для реализации различных поведений и заставить их действовать так же, как встроенные классы Python. Ниже вы увидите примеры двух наиболее распространенных: __str__
и __repl__
Отказ Используя эти два метода, вы можете реализовать, как ваши объекты отображаются в виде строк, которые будут важны при отладке и представлении информации пользователю. Переопределение этих методов добавляет гибкость и мощность Python.
__str__
Способ класса используется, когда Python печатает объект. Этот магический метод называется утра
Встроенная функция.
class DemoMagic(): def display(self): print("Demo Magic class") varDemo = DemoMagic() varDemo.display() str(varDemo)
Выход:
Demo Magic class '<__main__.DemoMagic object at 0x000002A7A7F64408>' class DemoMagic(): def display(self): print("Demo Magic class") def __str__(self): return "Override of str function" varDemo = DemoMagic() varDemo.display() str(varDemo)
Выход:
Demo Magic class 'Override of str function'
__repr__
Способ класса используется для отображения деталей значений объекта. Этот магический метод называется встроенным репре
функция.
class Person(object): def __init__(self, firstname, lastname): self.first = firstname self.last = lastname def __repr__(self): return "%s %s" % (self.first, self.last) Tom = Person("Tom", "Sawyer") repr(Tom)
Выход
'Tom Sawyer'
Вот список магических методов. Вы можете узнать больше о них здесь ( https://www.tutorialsteacher.com/python/magic-methods-in-python ) И подумайте, как переопределить их, чтобы соответствовать вашим потребностям:
'__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__'
3 – Абстрактные классы
Абстрактный класс – это план, что подклассы должны следовать. An abstract class is a blueprint that subclasses must follow. It can be viewed as a contract between the abstract class and the subclass. The abstract class tells you what to do by providing an empty abstract method and the subclass must implement it. By default, you must override the abstract methods defined by the abstract class. In other terms, we are providing a common interface for different implementations of a class. This is very useful for large projects where certain functionality must be implemented. Он можно рассматривать как договор между абстрактным классом и подклассом. An abstract class is a blueprint that subclasses must follow. It can be viewed as a contract between the abstract class and the subclass. The abstract class tells you what to do by providing an empty abstract method and the subclass must implement it. By default, you must override the abstract methods defined by the abstract class. In other terms, we are providing a common interface for different implementations of a class. This is very useful for large projects where certain functionality must be implemented. Абстрактный класс говорит вам, что делать, предоставляя пустой абстрактный метод, а подкласс должен его реализовать. По умолчанию вы должны переопределить абстрактные методы, определенные абстрактным классом. В других условиях мы предоставляем общий интерфейс для разных реализаций класса. Это очень полезно для крупных проектов, где необходимо реализовать определенные функциональные возможности.
Вот пример абстрактного класса и перевысимых методов в подклассах.
from abc import ABC, abstractmethod class Animal(ABC): @abstractmethod def whoami(self): pass class Dog(Animal): def move(self): print("I am a dog") class Cat(Animal): def move(self): print("I am a cat")
Вывод
Переопределение – это базовая концепция, используемая во многих местах в объектно-ориентированном программировании. Вы должны понимать, что он сможет реализовать лучшие классы и изменять их поведение. Эта статья показывает вам несколько примеров, в которых вы можете использовать переопределение в Python. Другие понятия, упомянутые, которые стоит узнать больше о следующих достопримечательностях: магический метод и абстрактные классы.