Repository navigation
Expand file tree
/
Copy pathmodule_5_3.py
More file actions
147 lines (130 loc) · 8.08 KB
/
Copy pathmodule_5_3.py
File metadata and controls
147 lines (130 loc) · 8.08 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
# Домашняя работа по уроку "Перегрузка операторов"
# Создаю класс House
class House:
# Создаю конструктор класса House с помощью ключевого слова __init__
def __init__(self, name, number_of_floors):
# Создаю два поля: self.name - имя, self.number_of_floors - кол-во этажей
self.name = name
self.number_of_floors = number_of_floors
# Создаю метод класса go_to() выводящий на экран(в консоль) значения от 1 до new_floor(включительно).
def go_to(self, new_floor):
if self.number_of_floors > new_floor > 0:
for floor in range(new_floor+1):
print(f'Этаж № {floor}')
else:
print('Такого этажа не существует')
# Реализую магический метод __len__()
def __len__(self):
return self.number_of_floors
# Реализую магический метод __str__()
def __str__(self):
return f'Название: {self.name}, кол-во этажей: {self.number_of_floors}'
# Реализую магический метод таким образом, чтобы зайдя в первое условие,
# интерпретатор при необходимости зашёл в следующее, поэтому используем конструкцию if-elif
# в отладке, конечно, яснее будет видно, когда два if принудительно и независимо друг от друга
# вычисляются, но мне этого не надо. Первое условие прошло, значит всё нормально (второе страхует, а
# если случится аномалия, то просто вернём False, что соответствует действительности).
# Здесь нужно вернуть не объект типа House, а значение True / False, поэтому я собственно и не создаю
# как в методе __add__() новый экземпляр типа House.
# Остальные магические методы до перегрузки сложения сделаны по аналогии с методом __eq__()
# По искав в интернете ответ на вопрос почему и зачем в задании с нас требуют использование isinstance(),
# я пришёл к выводу, что это важно для того, чтобы быть точно уверенным в том, что объекты, которые я сравниваю
# точно объекты одного типа, типы полей класса точно совпадают с каждым типом каждого поля моего класса.
# Не появится какого-то неожиданного поведения или ошибок несовместимости.
# Иными словами, если условие с использованием isinstance() выполнено, значит операция типобезопасна
# и однозначно выполнится правильно.
# Это, в том числе может служить ограничением для сложения только наших экземпляров и хорошим способом
# (через принудительный вызов ошибки) запрещать сложение экземпляра нашего класса с встроенным типом данных.
def __eq__(self, other):
if isinstance(other, House):
return self.number_of_floors == other.number_of_floors
elif isinstance(other.number_of_floors, int):
return self.number_of_floors == other
else:
return False
def __lt__(self, other):
if isinstance(other, House):
return self.number_of_floors < other.number_of_floors
elif isinstance(other.number_of_floors, int):
return self < other
else:
return False
def __le__(self, other):
if isinstance(other, House):
return self.number_of_floors <= other.number_of_floors
elif isinstance(other.number_of_floors, int):
return self <= other
else:
return False
def __gt__(self, other):
if isinstance(other, House):
return self.number_of_floors > other.number_of_floors
elif isinstance(other.number_of_floors, int):
return self > other
else:
return False
def __ge__(self, other):
if isinstance(other, House):
return self.number_of_floors >= other.number_of_floors
elif isinstance(other.number_of_floors, int):
return self >= other
else:
return False
def __ne__(self, other):
if isinstance(other, House):
return self.number_of_floors != other.number_of_floors
elif isinstance(other.number_of_floors, int):
return self != other
else:
return False
# На многих обучающих сайтах по Python, но не на всех
# (тот же: https://www.toppr.com/guides/python-guide/tutorials/python-object-class/python-operator-overloading/
# или
# https://www.programiz.com/python-programming/operator-overloading ),
# которые я смог найти возвращают значения, так же как и в уроке - возвращая сумму полей, но вещь это не логичная.
# Мы складываем объекты, значит и возвращать должны объекты. Ниже представлена моя реализация.
# Try-catch-finally (из С#) или try-catch(...) (из С++) мы ещё не знаем, поэтому не будем пока гуглить,
# как это делается в Python и просто вернём то же число, в случае когда у нас произошла аномалия и
# внезапно объект у нас совсем не подходит. Логика в выборе if- elif / isinstance() и та же.
def __add__(self, value):
if isinstance(value, House):
return House(self.name, self.number_of_floors + value.number_of_floors)
elif isinstance(value, int):
return House(self.name, self.number_of_floors + value)
else:
return House(self.name, self.number_of_floors)
def __radd__(self, value):
if isinstance(value, House):
return House(self.name, value.number_of_floors + self.number_of_floors)
elif isinstance(value, int):
return House(self.name, value + self.number_of_floors)
else:
return House(self.name, self.number_of_floors)
def __iadd__(self, value):
if isinstance(value, House):
self.number_of_floors += value.number_of_floors
return House(self.name, self.number_of_floors)
elif isinstance(value, int):
self.number_of_floors += value
return House(self.name, self.number_of_floors)
else:
return House(self.name, self.number_of_floors)
# Создаю 2 объекта класса House с произвольным названием и количеством этажей
h1 = House('ЖК Эльбрус', 10)
h2 = House('ЖК Акация', 20)
# Вызываю методы __len__() и __str__() у этого объекта с произвольным числом
print(h1)
print(h2)
print(h1 == h2) # __eq__
h1 = h1 + 10 # __add__
print(h1)
print(h1 == h2)
h1 += 10 # __iadd__
print(h1)
h2 = 10 + h2 # __radd__
print(h2)
print(h1 > h2) # __gt__
print(h1 >= h2) # __ge__
print(h1 < h2) # __lt__
print(h1 <= h2) # __le__
print(h1 != h2) # __ne__