Skip to content

Commit a825068

Browse files
committed
OOP theory & problems
1 parent 3aad084 commit a825068

11 files changed

+358
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#Функция на декоратора:
2+
def F(Alpha):
3+
class Bravo:
4+
value = Alpha()
5+
Bravo.__name__ = f"My{Alpha.__name__}"
6+
return Bravo
7+
#Клас с декоратор
8+
@F # == Charlie = F(Charlie)
9+
class Charlie:
10+
def __init__(self):
11+
self.number = 123
12+
def show(self):
13+
print(f"Поле number: {self.number}")
14+
#Създаване на обект:
15+
obj = Charlie()
16+
#Проверка на резултата:
17+
obj.value.show()
18+
print(f"Клас на обекта obj: {obj.__class__.__name__}")
19+
print(f"Клас на полето value: {obj.value.__class__.__name__}")
20+
21+
#Чрез @F класът Charlie се предефинира (пренаписва). За основа се взема описанието на класа Charlie и с помощта на този клас се създава нов клас.
22+
#ТОЙ СЕ СЪЗДАВА В СЪОТВЕТСТВИЕ С ИНСТРУКЦИЯТА F(Charlie). Референция към създадения клас се записва в идентификатора Charlie.
23+
#На практика се изпълнява командата Charlie = F(Charlie). Затова ако по-рано референция към новия клас получавахме с инструкцията F(Charlie),
24+
#то сега референция към новия клас дава инструкцията Charlie. Затова и командата на ред 18 дава, че класът на обекта obj е всъщност MyCharlie,
25+
#а името на класа на полето value, когато бъде извикано - Charlie.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#Първи клас:
2+
class Alpha:
3+
"Това е клас алфа" #Този текстов литерал (ред) се нарича документиращ низ на класа
4+
pass
5+
#Втори клас:
6+
class Bravo:
7+
"Това е клас Bravo"
8+
pass
9+
#Информация за класовете:
10+
print(Alpha.__doc__)
11+
print(Bravo.__doc__)
12+
#Обекти на класовете:
13+
A = Alpha()
14+
B = Bravo()
15+
16+
#Изменение на документиращия низ:
17+
Alpha.__doc__ = "Първи клас"
18+
B.__class__.__doc__ = "Втори клас"
19+
20+
#Информация за класовете:
21+
print(A.__class__.__doc__)
22+
print(B.__doc__)
23+
24+
#До документиращия низ достигаме чрез 1. името на класа.__doc__ или 2.обектите на класа._class__.__doc__/ във втория случай чрез __class__ ние получаваме референция към класа на обекта./)
25+
print(A.__doc__)
26+
print(B.__doc__)
27+
#A.__class__.__doc__ != A.__doc__, защото обектът няма атрибут, съответно търсенето продължава в класа (във втория случай).
28+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#Декораторът е някаква инструкция, която на основата на описания клас позволява да бъде получен друг клас:
2+
#За целта се използва функция, която като аргумент получава някакъв обект(тъй като класовете се реализират посредством обекти) и връща като резултат друг обект, реализиращ друг клас.
3+
4+
#Функция, която получава референция към клас и връща като резултат референция към клас:
5+
def F(Alpha):
6+
#Вътрешен клас
7+
class Bravo:
8+
value = Alpha()
9+
Bravo.__name__ = "My" + Alpha.__name__
10+
return Bravo
11+
#Описание на клас
12+
class Charlie:
13+
#Конструктор
14+
def __init__(self):
15+
self.number = 123
16+
#Метод за показване стойността на полето:
17+
def show(self):
18+
print(f"Поле number: {self.number}")
19+
#Създаване на обект на основата на клас, получен при извикването на функцията:
20+
obj = F(Charlie)()
21+
#Проверка на резултата:
22+
obj.value.show()
23+
print(f"Клас на обекта obj: {obj.__class__.__name__}")
24+
print(f"Клас на полето value: {obj.value.__class__.__name__}")
25+
26+
#Функция F приема като аргумент клас. Технически обяснено в качеството на аргумент функцията получава референция към обект, посредством който се реализира клас.
27+
#
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#Ние получаваме достъп до обектите посредством променливи, които се отнасят към тях. Променливите не съдържат обектите в качеството на стойности.
2+
3+
from copy import *
4+
#Описвам клас:
5+
class MyClass:
6+
pass
7+
#Създавам обект:
8+
A = MyClass()
9+
#Полета на обекта:
10+
A.value = 100
11+
A.nums = [1,2,3]
12+
#Присвоявам референция към обекта:
13+
B = A
14+
#!Важно! Към този момент А и В се отнасят към ЕДИН И СЪЩИ АДРЕС в паметта и се отнасят към един и същи обект.
15+
#Копие на обекта:
16+
C = copy(A)
17+
#Пълно к0опие на обекта:
18+
D = deepcopy(A)
19+
print(f"Създадени са обектите")
20+
#Полета на обектите:
21+
print(f"A: {A.value} и {A.nums}")
22+
print(f"B: {B.value} и {B.nums}")
23+
print(f"C: {C.value} и {C.nums}")
24+
print(f"D: {D.value} и {D.nums}")
25+
print()
26+
print(f"A.value = 200 и А.nums[1] = 0")
27+
#Нови стойности за полетата:
28+
A.value = 200
29+
A.nums[1] = 0
30+
31+
#Полета на обектите:
32+
print(f"A: {A.value} и {A.nums}")
33+
print(f"B: {B.value} и {B.nums}")
34+
print(f"C: {C.value} и {C.nums}") #Обект С е 'повърхностно' копие на обект А. То се създава посредством копирането на стойностите на полетата в обект А.
35+
#value в копие С НЕ се променя, защото неговата стойност е ЧИСЛО, а поле nums ще има същата стойност, каквато има в обект А, защото ТЕ ИМАТ ЕДИН И СЪЩ АДРЕС.
36+
print(f"D: {D.value} и {D.nums}") #Обект D е цяло копие на обект А, съответно промени в него не се оказват.
37+
print(f"Изтрива се А")
38+
print()
39+
#Във всички копия, освен в D, понеже е deepcopy(), т.е. адреса му в паметта е същия като на клас MyClass, стойностите се променят.
40+
41+
#Изтривам променливата:
42+
del A
43+
print(f"B.value = 300 и B.nums[2] = 4")
44+
#Нови стойности за полетата:
45+
B.value = 300
46+
B.nums[2] = 4
47+
48+
#Полета на обектите:
49+
print(f"B: {B.value} и {B.nums}")
50+
print(f"C: {C.value} и {C.nums}")
51+
print(f"D: {D.value} и {D.nums}")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#Описание на клас:
2+
class MyClass:
3+
#Конструктор:
4+
def __init__(self): #Init method is also called CONSTRUCTOR
5+
self.value = 123
6+
print(f'Създава се обект: {self.value}')
7+
#Destructor/Деструктор:
8+
def __del__(self):
9+
print(f'Изтрива се обект {self.value}') #Del method is also called DESTRUCTOR
10+
#Метод за присвояване на стойност на полето:
11+
def set(self,n):
12+
self.value = n
13+
14+
#Метод за показване на стойността на полето:
15+
def show(self):
16+
print(f"Поле на обекта: {self.value}")
17+
#Създаване на обект:
18+
obj = MyClass()
19+
#Извикване на методите от обекта:
20+
obj.show()
21+
obj.set(100)
22+
#Извикване на методите ОТ КЛАСА:
23+
MyClass.show(obj)
24+
MyClass.set(obj, 200)
25+
26+
#Проверка на стойността на полето:
27+
obj.show()
28+
29+
#Явно извикване на конструктора:
30+
MyClass.__init__(obj)
31+
#Явно извикване на деструктора:
32+
MyClass.__del__(obj)
33+
34+
#Проверка на стойността на полето:
35+
obj.show()
36+
37+
#Изменение на стойността на полето:
38+
obj.value = 321
39+
obj.show()
40+
41+
#Явно извикване на конструктора чрез обекта:
42+
obj.__init__()
43+
44+
#Явно извикване на деструктора чрез обекта:
45+
obj.__del__()
46+
47+
#Важно е да се подчертае, че само по себе си извикването на конструктора или деконструктора не води съответно до създаването/изтриването на обект.
48+
#Конструкторът е метод, който се извиква автоматично непосредствено след създаването на обекта, а деструкторът е метод, който се извиква автоматично непосредсвтвено преди изтриването на обекта.
49+
50+
#Проверка на стойноста на полето:
51+
obj.show()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
class MyClass:
2+
#Поле на класа:
3+
color = 'Червен'
4+
#Методи на класа:
5+
def set(txt):
6+
MyClass.color = txt
7+
def show():
8+
print(MyClass.color)
9+
#Извикване на методите на класа:
10+
MyClass.show()
11+
MyClass.set("Зелен")
12+
#Показване стойността на полето на класа:
13+
print(MyClass.color)
14+
#Задаваме нова стойност за полето на класа:
15+
MyClass.color = 'Син'
16+
#извикваме метода на класа:
17+
MyClass.show()
18+
#Създаваме обекти на класа:
19+
A = MyClass()
20+
B = MyClass()
21+
#Проверка на стойността на полето:
22+
print(f'Клас: {MyClass.color}')
23+
print(f'Обект А: {A.color}')
24+
print(f'Обект В: {B.color}')
25+
#Присвояваме стойност на полето:
26+
A.color = 'Бял'
27+
#Проверяваме стойността на полето:
28+
print(f'Клас: {MyClass.color}')
29+
print(f'Обект А: {A.color}')
30+
print(f'Обект В: {B.color}')
31+
#Защо при извикването на Обект А се принтира 'Бял', а не 'Син'? Защото на пръв поглед обекти А и В са еднакви, но всъщност не са- те имат различни места в РАМ паметта.
32+
MyClass.color = 'Оранжев'
33+
print(f'Клас: {MyClass.color}')
34+
print(f'Обект А: {A.color}')
35+
print(f'Обект В: {B.color}')
36+
#Защо при изхода обект А остана 'Бял'? Защото при създаването на обекти А/В на класа MyClass, ние всъщност създаваме референция към самия обект MyClass,
37+
#! Класът се реализира на основата на някакъв обект (в случая А и В), а името на класа съдържа РЕФЕРЕНЦИЯ към самия обект.
38+
print(type(A))
39+
print(type(B))
40+
print(type(MyClass))
41+
print()
42+
#Чрез type()/id() ние разбираме типа на данните (в случая класове) и техните адреси в РАМ паметта. Всички три типа, макар и на пръв поглед еднакви, са различни, ознавайки това от различните им адреси в паметта.
43+
print(id(A))
44+
print(id(B))
45+
print(id(MyClass))
46+
print()
47+
48+
MyClass.color = ("Жълт")
49+
#Проверяваме стойността на полето:
50+
print(f'Клас: {MyClass.color}')
51+
print(f'Обект А: {A.color}')
52+
print(f'Обект В: {B.color}')
53+
print()
54+
#Защо А.колор връща 'син', а класът и обект В връщат 'Жълт'? Защото на обект В, който е референция към класа, не е придадена стойност на променлива color.
55+
del A.color
56+
print(f'Клас: {MyClass.color}')
57+
print(f'Обект А: {A.color}')
58+
print(f'Обект В: {B.color}')
59+
#След изтриване на обект А, търсенето на A.color няма да се осъществява в обект А, а в класа MyClass.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
https://pastebin.com/Vx6M6bRy
2+
https://pastebin.com/2ganVicZ
3+
https://pastebin.com/63v9mXqe
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#Първо заявеният атрибут се търси в обекта, а ако не бъде намерен там - тогава се търси в класа, на основата на който е създаден обектът.
2+
#Достъп до речника, посредством койот е реализиран обектът, може да бъде получен с помощта на специалния метод __dict__
3+
#Ако полето е заявено за класа, ще получим речника за обекта, посредством който е реализиран класът. Ако полето се заявява за обекта, като резултат ще получим речника, посредством който е реализиран даденият обект.
4+
5+
#Създаваме два класа:
6+
class Alpha:
7+
pass
8+
class Bravo:
9+
name = 'Bravo'
10+
def display():
11+
print(f"Поле name: {Bravo.name}")
12+
def show(self): #self е аргумент - референция към обекта, от който се извиква методът.
13+
print(f'Поле value: {self.value}') #При извикването му се показва стойността на value от обекта, от който се извиква методът.
14+
def __init__(self):
15+
self.value = 123
16+
#Сега създавам обектите:
17+
A = Alpha()
18+
B = Bravo()
19+
20+
#Атрибутите на първия клас:
21+
print("Клас Alpha")
22+
n = 1
23+
for s in Alpha.__dict__:
24+
print("["+str(n)+"] "+s+":", Alpha.__dict__[s])
25+
n += 1
26+
#Атрибути на втория клас:
27+
print(f"Клас Bravo:")
28+
n = 1
29+
for s in Bravo.__dict__:
30+
print(f"[{n}] {s}: {Bravo.__dict__[s]}")
31+
n += 1
32+
#Атриб ите:
33+
print(f"Обект А: {A.__dict__}")
34+
print(f"Обект В: {B.__dict__}")
35+
#И двата класа съдържат повече атрубити, отколкото са оказани в кода. Тези 'скрити' атрибути са т.нар 'служебни' атрибути, които са достъпни за класовете по подразбиране. Сред тях е и полето __dict__.
36+
#A и В са обекти, референции към класовете Алфа и Браво. За обектите се показват само онези атрибути, които са зададени непосредствено за обекта.
37+
38+
#Извикване на метода на класа:
39+
Bravo.display()
40+
print()
41+
#Създаване на атрибут на класа:
42+
Alpha.display = Bravo.display #Вследствие от тази команда в клас Alpha се създава атрибут display. Стойност на атрибута се явява адресът на обекта, чрез който е реализиран метод display() от класа Bravo.
43+
44+
#Изтриване на атрибут на класа:
45+
del Bravo.display
46+
#Извикване на метода от обекта:
47+
B.show()
48+
#Създаване на атрибут на класа:
49+
A.color = 'Червен'
50+
#Създаване на атрибут на обекта:
51+
B.show = lambda: print(f"Обект В: {B.value}") #Използвайки ламбда-функция създавам атрибут value към обект В, аналогично на B.value = Bravo.value
52+
53+
#Атрибути на първия клас:
54+
print(f"Клас Alpha")
55+
56+
n = 1
57+
for s in Alpha.__dict__:
58+
print(f"[{n}] {s}: {Alpha.__dict__[s]}")
59+
n += 1
60+
print()
61+
#Атрибути на втория клас
62+
63+
n = 1
64+
for s in Bravo.__dict__:
65+
print(f"[{n}] {s}: {Bravo.__dict__[s]}")
66+
n += 1
67+
68+
#Атрибути на обектите:
69+
print(f"Обект А: {A.__dict__}")
70+
print(f"Обект В: {B.__dict__}")
71+
72+
print()
73+
74+
#Извикване на методи:
75+
Alpha.display()
76+
Bravo.show(B)
77+
B.show()
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import statistics
2+
3+
4+
class MyClass():
5+
def __init__(self, arg_list):
6+
arg_list = [x for x in arg_list if x.isnumeric()]
7+
self.arg_list = arg_list
8+
self.arg_list = [int(x) for x in self.arg_list]
9+
10+
def show(self):
11+
return print(f'The argument list: {self.arg_list}')
12+
13+
def average(self):
14+
return print(f'Average value in args list is: {statistics.mean(self.arg_list):.2f}')
15+
16+
17+
current_list = [x for x in input().split()]
18+
obj = MyClass(current_list)
19+
obj.show()
20+
obj.average()
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class MyClass():
2+
def __init__(self, el_one, el_two):
3+
self.el_one = el_one
4+
self.el_two = el_two
5+
6+
def show(self):
7+
if type(self.el_one) == str and type(self.el_one) == type(self.el_two):
8+
return self.el_one + self.el_two
9+
elif type(self.el_one) == int and type(self.el_one) == type(self.el_two):
10+
return self.el_one + self.el_two
11+
12+
13+
obj = MyClass(1, 2)
14+
print(obj.show())
15+
16+
obj_2 = MyClass('Hello ', 'World!')
17+
print(obj_2.show())

OOP/small OOP problems/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)