Python
План
Спадкування
Приклад 1
Приклад 2
Приклад 2
Множинне спадкоємство
Приклад 3
Приклад 3
Класи старого і нового типів
Приклад
Приклад 4
Порядок вирішення методів (MRO)
Порядок вирішення методів (MRO)
Порядок вирішення методів (MRO)
Отримання доступу до атрибутів суперкласу
Приклад 5
Приклад 5
Приклад 5
Приклад 5
Визначення типу об'єкта
Поліморфізм
Качина типізація
Поліморфізм
349.50K
Category: programmingprogramming

Python

1. Python

ООП
1

2. План

1.
2.
3.
Спадкування
Множинне спадкування
Порядок вирішення методів
2

3. Спадкування

Спадкування - механізм мови, що дозволяє
описати новий клас на основі вже існуючого
(батьківського, базового) класу.
Клас-нащадок може додати власні методи і
властивості, а також користуватися
батьківськими методами і властивостями.
Дозволяє будувати ієрархії класів.
Є одним з основних принципів об'єктно –
орієнтованого програмування.
3

4. Приклад 1

class Base:
def method(self):
print("Hello!")
class Child(Base):
pass
obj=Child()
obj.method()
4

5. Приклад 2

class Figure(object):
def __init__(self, side):
self.side = side
class Square(Figure):
def draw(self):
for i in range(self.side):
print('* ' * self.side)
class Triangle(Figure):
def draw(self):
for i in range(self.side):
print('* ' * i)
5

6. Приклад 2

def main():
square = Square(10)
square.draw()
print()
triangle = Triangle(5)
triangle.draw()
if __name__ == '__main__':
main()
*****
*****
*****
*****
*****
*
**
***
****
>>>
6

7. Множинне спадкоємство

При множинному спадкуванні у класу може
бути більш одного предка. В цьому
випадку клас успадковує методи всіх
предків. Перевага такого підходу в більшій
гнучкості, проте він може бути
потенційним джерелом помилок.
Список базових класів вказується через кому
в круглих дужках після імені даного класу:
class Pegasus(Horse, Bird) :
pass
7

8. Приклад 3

class Bird(object):
def fly(self):
print('I am flying.')
class Horse(object):
def run(self):
print('I am running.')
class Pegasus(Horse, Bird):
pass
def main():
bird = Bird()
horse = Horse()
pegasus = Pegasus()
8

9. Приклад 3

bird.fly()
# bird.run() # Error
print()
# horse.fly() # Error
horse.run()
print()
I am flying.
pegasus.fly()
pegasus.run()
I am running.
if __name__ == '__main__':
main()
I am flying.
I am running.
9

10. Класи старого і нового типів

У версіях до 2. 2 деякі об'єктно - орієнтовані можливості
Python були помітно обмежені. Починаючи з версії 2. 2,
об'єктна система Python була істотно перероблена і
доповнена.
З метою сумісності з існуючим кодом в Python 2 існують
дві системи типів: класи нового типу (new-style classes)
і класи старого типу (old-style classes, classic classes).
Для створення класу нового типу слід успадкувати його
від будь-якого іншого класу нового типу. Всі стандартні
класи є класами нового типу. Базовим з них є клас
object.
Якщо в Python 2 не вказувати базовий клас або
успадкувати його від іншого класу старого типу, то
даний клас є класом старого типу.
10

11. Приклад

>>> class
MyObject(object):
pass
>>> type(MyObject)
<class 'type'>
>>>
>>> class MyObject:
pass
>>> type(MyObject)
<class 'type'>
11

12. Приклад 4

class A(object):
def method(self):
print('A method')
class B(A):
pass
class C(A):
def method(self):
print('C method')
А method
>>>
C method
>>>
class D(B, C):
pass
obj = D()
obj.method() # 'C method‘
[<class '__main__.D'>, <class '__main__.B'>, <class
#print(D.mro())
'__main__.C'>, <class '__main__.A'>, <class 'object'>]
12

13. Порядок вирішення методів (MRO)

Якщо атрибут, до якого
здійснюється доступ, не
знайдений в поточному класі,
проводиться його пошук в
класах - батьків.
Порядок, в якому
інтерпретатор переглядає
базові класи, визначається
лінеаризацією даного класу,
так званої MRO (Method
Resolution Order). Вона
зберігається в атрибуті класу
__ mro__.
MRO будується за допомогою
алгоритму C3 -лінеарізаціі
13

14. Порядок вирішення методів (MRO)

Властивості лінеаризації:
стійкість і розширюваність;
монотонність: в лінеаризації класу нащадка дотримується той же порядок
проходження класів - прабатьків, що і в
лінеаризації класу - батька;
властивість локального старшинства: в
лінеаризації класу - нащадка дотримується
той же порядок проходження класів батьків, що і в його оголошенні
Лінеаризація будується тільки для класів нового типу. У класах старого
типу пошук атрибутів відбувається за допомогою пошуку в глибину, що
може давати некоректні результати при ромбоподібному спадкуванні. 14

15. Порядок вирішення методів (MRO)

У прикладі зліва лінеаризація
класу D, тобто D. __ Mro__,
виглядає як [D, B, C, A].
Таким чином, якщо спробувати
викликати obj.method (), де obj екземпляр класу D, буде
викликаний метод класу C.
Якби A був класом старого типу в
Python 2, то був би викликаний
метод method класу A, що в
даному випадку є неправильною
поведінкою, так як він
перевизначений в класі C,
спадкоємцем якого є клас D. Це
одна з причин, по яким слід
використовувати класи нового
типу.
15

16. Отримання доступу до атрибутів суперкласу

Якщо в даному класі метод або атрибут був
перевизначеним, а потрібний доступ до
відповідного атрибуту суперкласу, це можна
зробити двома способами:
super повертає
спеціальний
проміжний
об'єкт, який
надає доступ до
атрибутів
наступного
класу в __mro__.
шляхом явного звернення до атрибуту
необхідного класу: BaseClass.method (self)
за допомогою інстанціонування спеціального
проксі - об'єкта класу super (виглядає , як виклик
функції).
В Python 2 як параметри конструктора super
передаються ім'я поточного класу і посилання
на екземпляр поточного класу:
super (MyClass, self) .method ()
В Python 3 можна не вказувати нічого і дані
параметри будуть отримані автоматично:
super () .method ()
# те ж саме, що
super (__ class__, self) .method ()
16

17. Приклад 5

class Animal(object):
def __init__(self):
self.can_fly = False
self.can_run = False
def print_abilities(self):
print(self.__class__.__name__)
print('Can fly:', self.can_fly)
print('Can run:', self.can_run)
print()
17

18. Приклад 5

class Bird(Animal):
def __init__(self):
super().__init__()
self.can_fly = True
class Horse(Animal):
def __init__(self):
super().__init__()
self.can_run = True
class Pegasus(Horse, Bird):
pass
18

19. Приклад 5

def main():
bird = Bird()
bird.print_abilities()
horse = Horse()
horse.print_abilities()
pegasus = Pegasus()
pegasus.print_abilities()
if __name__ == '__main__':
main()
19

20. Приклад 5

Bird
Can fly: True
Can run: False
Horse
Can fly: False
Can run: True
Pegasus
Can fly: True
Can run: True
20

21. Визначення типу об'єкта

Тип * даного об'єкта можна визначити за допомогою
атрибута __class__ і вбудованої функції type (obj).
Атрибут класу __bases__ зберігає кортеж (незмінний
список) базових класів.
• Оскільки відношення успадкування є транзитивним,
в загальному випадку для перевірки того, чи є даний
об'єкт екземпляром заданого класу або чи є даний
клас підклассом заданого класу, ці атрибути потрібно
перевіряти рекурсивно. Існують вбудовані функції, які
це роблять.
• isinstance (obj, cls) перевіряє, чи є obj екземпляром
класу cls або класу, який є спадкоємцем класу cls;
issubclass (cls, base) перевіряє, чи є клас cls
спадкоємцем класу base.
21

22. Поліморфізм

Поліморфізм – це здатність однаковим чином обробляти
дані різних типів.
Поліморфізм є фундаментальною властивістю системи
типів.
1. Спеціальний
поліморфізм.
1. Статична
неполіморфна
типізація.
2. Параметричний
поліморфізм.
2. Статична поліморфна
типізація.
3. Поліморфізм
підтипів.
3. Динамічна типізація.
22

23. Качина типізація

Неявна типізація, латентна типізація або качина
типізація (англ. Duck typing) - вид динамічної
типізації, при якій межі використання об'єкта
визначаються його поточним набором методів і
властивостей, на противагу спадкоємства від певного
класу. Тобто вважається, що об'єкт реалізує
інтерфейс, якщо він містить всі методи цього
інтерфейсу, незалежно від зв'язків в ієрархії
успадкування та приналежності до якого-небудь
конкретного класу.
Назва терміна походить від англійського «duck test»
( «качиний тест»), який в оригіналі звучить як:
«If it looks like a duck, swims like a duck and
quacks like a duck, then it probably is a duck».
( «Якщо це виглядає як качка, плаває як качка і
крякає як качка, то, ймовірно, це качка».).
23

24. Поліморфізм

def get_last(x):
return x[-1]
print (get_last([1, 2, 3]))
print (get_last("abcd"))
24
English     Русский Rules