logo

Порядок вирішення методів у Python

У цьому підручнику ми дізнаємося про порядок вирішення методів, який також відомий як MRO. Це важлива концепція успадкування Python.

Порядок вирішення методів описує шлях пошуку класу, який Python використовує для отримання відповідного методу в класах, які містять мультинаслідування.

вступ

Як ми знаємо, клас, який успадковується, називається підкласом або батьківським класом, тоді як клас, який успадковує, називається дочірнім класом або підкласом. У мульти-наслідуванні клас може складатися з багатьох функцій, тому техніка порядку вирішення методів використовується для пошуку порядку, в якому виконується базовий клас.

різниця між гігабайтом і мегабайтом

Простими словами: «Метод або атрибути досліджуються в поточному класі, якщо метод відсутній у поточному класі, пошук переміщується до батьківських класів і так далі». Це приклад пошуку в глибину.

Він відіграє важливу роль у множинному успадкуванні, коли той самий метод можна знайти в кількох суперкласах.

Щоб зрозуміти це краще, давайте подивимося, як ми можемо ним скористатися.

приклад -

 class A: def myname(self): print('I am a class A') class B(A): def myname(self): print('I am a class B') class C(A): def myname(self): print('I am a class C') c = C() print(c.myname()) 

Вихід:

 I am a class C 

Пояснення -

У наведеному вище коді є множинне успадкування. Ми визначили три класи під назвами A, B і C, і ці класи мають однакову назву методу моє ім'я(). Ми створили клас об’єктів C. Об’єкт викликав клас C, а не клас, тоді як клас C успадкував метод класу A.

Порядок дотримується у наведеному вище коді клас B -> клас A. Цей метод відомий як MRO (порядок вирішення методу).

Давайте розберемо інший приклад множинного успадкування.

приклад -

 class A: def myname(self): print(' I am a class A') class B(A): def myname(self): print(' I am a class B') class C(A): def myname(self): print('I am a class C') # classes ordering class D(B, C): pass d = D() d.myname() 

Вихід:

 I am a class B 

Пояснення -

У наведеному вище коді ми створили інший клас D без визначення атрибутів класу, які успадкували класи B і C. Коли ми викликали метод моє ім'я(), він переходить до класу D і шукає моє ім'я( ) функція. Але клас D не має жодної декларації. Отже, пошук переходить до класу B, отримує своє моє ім'я() і повертає результат. Пошук буде проходити наступним чином.

 Class D -> Class B -> Class C -> Class A 

Якщо клас B не має методу, він викличе метод класу C.

Тут ми пропонуємо вам видалити метод класу B і перевірити, що відбувається. Зробивши це, ви отримаєте уявлення про те, як працює роздільна здатність методу.

Порядок старого та нового стилю

У старішій версії Python (2.1) ми обмежені у використанні старих класів, але Python (2.2 і далі), ми можемо використовувати нові класи. За замовчуванням Python 3 має оригінальні (нові) класи. Перший батьківський клас нового стилю успадковує кореневий клас «об’єкт» Python. Давайте розглянемо наступний приклад -

приклад -

 # Old style class class OldStyleClass: pass # New style class class NewStyleClass(object): pass 

Стиль оголошення обох класів відрізняється. У роздільній здатності методу класи старого стилю дотримуються алгоритму «глибина спочатку зліва направо» (DLR), тоді як нові класи стилю використовують алгоритм лінеаризації C3 під час виконання множинного успадкування.

шлях, встановлений у java

Алгоритм DLR

Python створює список класів, реалізуючи множинне успадкування між класами. Цей список використовується для визначення того, який метод має бути викликаний екземплярами.

Ми можемо припустити, що працюємо за його назвою, оскільки дозвіл методу шукатиме спочатку в глибину, а потім переходитиме зліва направо. Нижче наведено приклад.

приклад -

 class A: pass class B: pass class C(A, B): pass class D(B, A): pass class E(C,D): pass 

Спочатку алгоритм шукатиме викликаний метод у класі екземпляра. Якщо не знайдено, воно переходить до перших батьків, якщо там також не знайдено. Він шукатиме батьківського елемента. Це триватиме до кінця успадкування класів.

У наведеному вище прикладі порядок вирішення методів буде таким:

 class D -> class B -> class A -> class C -> class A 

Але А не може бути присутнім двічі, тому -

 class D -> class B -> class A -> class C -> 

Цей алгоритм показує дивну поведінку в той час. Давайте розглянемо наведений нижче приклад.

приклад -

 class A: pass class B: pass class C(A, B): pass class D(B, A): pass class E(C,D): pass 

Згідно з алгоритмом DLR, порядок буде E, C, D, B, A. Класи A і B переміняються в класі C, що є дуже неоднозначним. Це означає, що алгоритм не зберігає властивість монотонності.

Самуеле Пердоні був першою людиною, яка виявила невідповідність між алгоритмами MRO.

Алгоритм лінеаризації С3

Алгоритм лінеаризації C3 є кращою версією алгоритму DLR, оскільки він усуває неузгодженість. Цей алгоритм має деякі обмеження, наведені нижче.

  • Діти повинні випереджати своїх батьків.
  • Якщо певний клас успадковує один або більше класів, вони зберігаються в порядку, зазначеному в кортежі базового класу.

Правила алгоритму лінеаризації C3

  • Структура порядку вирішення методів визначається графом успадкування.
  • Користувач повинен відвідати суперклас лише після відвідування методів локальних класів.
  • Зберігайте монотонність

Метод для класу роздільної здатності методу

Python надає два способи отримати порядок вирішення методів класу - __mro__ атрибут або mro() метод. За допомогою цих методів ми можемо відобразити порядок методів, у якому вони вирішуються.

Давайте розберемося в наступному прикладі.

алфавіт до числа

приклад -

 class A: def myname(self): print(' I am a class A') class B(A): def myname(self): print(' I am a class B') class C(A): def myname(self): print('I am a class C') # classes ordering class D(B, C): pass # it prints the lookup order print(D.__mro__) print(C.mro()) 

Вихід:

 (, , , , ) [, , ] 

Як ми бачимо у наведеному вище виводі, ми отримуємо порядок розв’язання методів. Таким чином, алгоритм лінеаризації C3 працює для множинного успадкування.