-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathtest_oop1.py
More file actions
218 lines (162 loc) · 8.32 KB
/
test_oop1.py
File metadata and controls
218 lines (162 loc) · 8.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# Создание классов и объектов
def test_dog():
class Собака: # Класс "Собака"
def __init__(self, name): # Конструктор класса
self.name = name # У собаки есть имя и оно будет храниться в атрибуте name
def полаять(self): # Полаять
print(f"{self.name} говорит Гав!")
# Мы создаём объект класса Собака
моя_собака = Собака("Тузик")
моя_собака.полаять()
assert моя_собака.name == "Тузик"
# Второй объект класса Собака
вторая_собака = Собака("Шарик")
вторая_собака.полаять()
# == Инкапсуляция ==
# Использование инкапсуляции для защиты данных
class Circle: # Класс Круг
def __init__(self, radius): # Конструктор класса
self.radius = radius # Публичный атрибут
def perimeter(self): # Длина окружности
self._hidden_method()
self.__private_method()
return 2 * 3.14 * self.radius # Публичный метод
def area(self): # Публичный метод "площадь круга"
return 3.14 * self.radius * self.radius # Публичный метод
def _hidden_method(self):
print("Скрытый метод")
def __private_method(self):
print("Приватный метод - можно использовать только в этом классе")
def test_circle():
assert Circle(10).area() == 314.0
assert Circle(21).area() == 1384.74
assert abs(Circle(10).perimeter() - 62.8) < 0.001
c = Circle(10)
c._hidden_method()
# c.__private_method()
# Наследование и переопределение методов
# Реализация полиморфизма
class Animal: # Базовый класс "Животное"
def __init__(self, name): # Конструктор класса
self.name = name # Публичный атрибут
def speak(self):
print("Я не знаю как я говорю!")
def speak_with_name(self):
return f"{self.name} говорит: {self.speak()}"
class Dog(Animal): # Класс "Собака"
def speak(self): # Переопределение метода
return "Гав!"
class Cat(Animal): # Класс "Кошка"
def speak(self): # Переопределение метода
return "Мяу!"
class Cow(Animal): # Класс "Корова"
def speak(self): # Переопределение метода
return "Муу!"
class Fish(Animal): # Класс "Рыба"
def speak(self): # Переопределение метода
return "Буб!"
def animal_sound(animal: Animal):
print(animal.speak_with_name())
def test_animals():
assert Dog("Тузик").speak() == "Гав!"
assert Cat("Пушок").speak() == "Мяу!"
assert Cow("Бурёнка").speak() == "Муу!"
assert Fish("Дори").speak() == "Буб!"
animals = [Dog("Тузик"), Cat("Пушок"), Cow("Бурёнка"),
Cat("Рыжик"), Fish("Дори")]
for animal in animals:
print(animal.speak_with_name()) # Полиморфизм
for animal in animals:
animal_sound(animal)
# == Обновление метода ==
# Иногда вы можете захотеть сохранить исходное поведение метода,
# но добавить к нему дополнительную функциональность.
# Это можно сделать с помощью функции super():
class SmallDog(Dog):
def speak(self):
print("Будьте осторожны с маленькой собакой!")
# вызываем исходный метод из родительского класса
return super().speak() + " ...но это маленькая собака."
def test_small_dog():
small_dog = SmallDog("Малыш")
assert small_dog.speak() == "Гав! ...но это маленькая собака."
# == Расширение методов ==
# Добавление новой функциональности к классам
# без изменения исходного кода класса.
# Это можно делать с помощью наследования или миксинов
# Миксин — это класс, который содержит методы для использования в других классах
# Миксин "Вилять хвостом"
class WagTailMixin:
def __init__(self, name):
self.name = name
def wag_tail(self): # Новый метод "махать хвостом"
print(f"{self.name} машет хвостом!")
# Класс "Счастливая собака"
class HappyDog(Dog, WagTailMixin): # Множественное наследование
pass
def test_happy_dog():
h_dog = HappyDog("Бобик")
print(h_dog.speak())
h_dog.wag_tail()
# Класс "Несчастный кот"
class UnhappyCat(Cat, WagTailMixin): # Множественное наследование
pass
def test_unhappy_cat():
u_cat = UnhappyCat("Рыжик")
print(u_cat.speak())
u_cat.wag_tail()
# Пример использования инкапсуляции
class BankAccount:
# Здесь баланс счёта __balance — приватный атрибут.
# Он не доступен извне класса напрямую,
# и чтобы получить его значение,
# нужно использовать метод get_balance
def __init__(self, balance=0):
self.__balance = balance
self.__transactions = [f"Начальный баланс: {balance}"]
def deposit(self, amount): # Внести сумму на счёт
if amount > 0:
self.__balance += amount
self.__transactions.append(f"Пополнили на {amount}")
return self.__balance
else:
print(f"{amount} - некорректная сумма для депозита "
f"(должна быть положительной)")
def withdraw(self, amount): # Снять сумму со счёта
if 0 < amount <= self.__balance:
self.__balance -= amount
self.__transactions.append(f"Сняли {amount}")
return self.__balance
else:
print(f"{amount} - некорректная сумма для снятия "
f"(должна быть положительной и <= баланса)")
def get_balance(self): # Получить текущий баланс
return self.__balance
def show_transactions(self): # Показать список транзакций
for t in self.__transactions:
print(t)
print(f"Текущий баланс: {self.__balance}")
def test_bank_account():
account = BankAccount(1000)
assert account.get_balance() == 1000
print(account.deposit(500))
assert account.get_balance() == 1500
print(account.deposit(-100))
assert account.get_balance() == 1500
assert account.withdraw(200) == 1300
account.show_transactions()
class Car: # Класс "Машина"
def __init__(self): # Конструктор класса
self.__update_software() # Вызов приватного метода
def drive(self): # Публичный метод
print("Машина едет")
# Метод __update_software приватный и предназначен
# для внутреннего использования в классе.
# Может быть полезно, например, чтобы предотвратить
# вызов этого метода извне или из производных классов
def __update_software(self): # Приватный метод
print("Обновление программного обеспечения")
def test_car():
car = Car()
car.drive()
# car.__update_software() # Мы не можем так вызвать