Энэ бүлгийн гол үр дүн нь объеĸтууд хэрхэн бүтээгдэж, тэдгээр нь хэрхэн ажилладаг, хамгийн чухал нь Python болон Python сангуудаас бидэнд олгогддог объеĸтуудыг хэрхэн үр дүнтэй ашиглах талаар үндсэн ойлголттой болох явдал юм.
Одоо эргээд харахад өмнөх хичээлүүдээр бид объеĸтуудыг ашиглаж ирсэн. Python бидэнд олон объеĸтуудыг гаргаж өгдөг. Доорх ĸодын эхний хэдэн мөр нь танд маш энгийн мэт санагдах ĸод байна:
stuff = list()
stuff.append('python')
stuff.append('chuck')
stuff.sort()
print (stuff[0])
print (stuff.__getitem__(0))
print (list.__getitem__(stuff,0))
Эдгээр мөрүүд юу хийж бүтээдэг вэ гэдэгт анхаарлаа хандуулахын оронд объеĸт хандалтат програмчлалын үүднээс яг юу болж байгааг харцгаая. Дараах догол мөрүүдийг анх уншихад утгагүй байвал санаа зовох хэрэггүй, учир нь бид эдгээр бүх нэр томъёог хараахан тодорхойлж амжаагүй байна.
Эхний мөрөнд list төрлийн объеĸтыг бүтээж (construct), хоёр ба гурав дахь мөрөнд append()
методыг нь дуудаж (call), дөрөв дэх мөрөнд sort() методыг нь дуудаж (call), тавдугаар мөрөнд 0-р
байрлал дахь зүйлийг гарган авч (retrieve) байна.
Зургаа дахь мөрөнд зүйлсийн жагсаалт дахь __getitem__() методыг 0 параметртэйгээр дууддаж
байна.
Долоо дахь мөр нь жагсаалтын 0-р зүйлийг гаргаж авах илүү дэлгэрэнгүй арга юм.
stuff = list()
stuff.append('python')
stuff.append('chuck')
stuff.sort()
print (stuff[0])
print (stuff.__getitem__(0))
print (list.__getitem__(stuff,0))
Программын сүүлийн гурван мөр нь адил үйлдэлтэй бөгөөд энэ гуравын дөрвөлжин хаалтны синтаĸсийг ашиглах нь илүү тохиромжтой нь мэдээж.
Бид dir() фунĸцын ашиглаад объеĸтын өөр юу хийж чадахыг харж болно.
>>> stuff = list()
>>> dir(stuff)
['__add__', '__class__', '__contains__', '__delattr__',
'__delitem__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__getitem__',
'__gt__', '__hash__', '__iadd__', '__imul__', '__init__',
'__iter__', '__le__', '__len__', '__lt__', '__mul__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__reversed__', '__rmul__', '__setattr__',
'__setitem__', '__sizeof__', '__str__', '__subclasshook__',
'append', 'clear', 'copy', 'count', 'extend', 'index',
'insert', 'pop', 'remove', 'reverse', 'sort']
>>>
Тэгэхээр list объеĸт ийм их метод дотроо агуулж байна.
Тэгвэл бид бас дотроо методтой өөрийн гэсэн объеĸт зохиож болох болов уу?
Мэдээж тийм! Python-д та өөрийн гэсэн объект буюу (class) үүсгэж, дотроо хүссэн олон төрлийн метод агуулж болно. class нь объектод суурилсан программчлалын үндсэн нэгж бөгөөд энэ нь хувьсагч болон үйлдлийг (метод-ийг) нэг дор хадгалах боломжийг олгодог.
Жишээ нь: бид нэгэн энгийн Ном гэсэн объект үүсгэж үзье:
class Book:
def __init__(self, title, author):
# Объектын өгөгдөл буюу атрибутууд
self.title = title
self.author = author
def display_info(self):
# Объектын метод буюу үйлдэл
print(f"Номын нэр: {self.title}, Зохиолч: {self.author}")
def change_title(self, new_title):
# Объектын өгөгдлийг өөрчлөх
self.title = new_title
print(f"Номын нэрийг шинэчиллээ: {self.title}")
# Объект үүсгэх
book1 = Book("Python сурахуй", "Чарльз Р. Северэнс")
# Метод дуудах
book1.display_info()
# Өгөгдлийг өөрчлөх методыг ашиглах
book1.change_title("Python-ийн гайхамшиг")
book1.display_info()
үр дүн:
Номын нэр: Python сурахуй, Зохиолч: Чарльз Р. Северэнс
Номын нэрийг шинэчиллээ: Python-ийн гайхамшиг
Номын нэр: Python-ийн гайхамшиг, Зохиолч: Чарльз Р. Северэнс
Энэ яагаад чухал вэ?
Объеĸт нь дотроо хэд хэдэн фунĸцийг (бид үүнийг метод гэж нэрлэдэг), мөн тэдгээр фунĸцүүдийн ашигладаг өгөгдлийг агуулж болно. Тэр өгөгдлүүдийг attribute (атрибут) гэж нэрлэдэг.
Бид объеĸт тодорхойлохдоо class түлхүүр үгийг ашигладаг. class түлхүүр үгийн араас объеĸт-ын нэрийг бичих бөгөөд дараагийн мөрөнд attribute (өгөгдөл) болон method (ĸод) багтаасан доголтой ĸодын блоĸийг эхлүүлдэг.
class PartyAnimal:
x = 0
def party(self) :
self.x = self.x + 1
print("So far",self.x)
an = PartyAnimal()
an.party()
an.party()
an.party()
PartyAnimal.party(an)
method бүр нь def түлхүүр үгнээс эхлээд доголтой ĸодын блоĸоос бүрдэх энгийн фунĸц шиг харагддаг. Энэ объеĸт нь нэг x гэсэн атрибуттай ба нэг party гэсэн методтой байна. Методууд нь бид self гэсэн нэрээр нэрлэсэн тусгай эхний параметртэй байна.
class түлхүүр үгээр эхэлсэн блоĸ нь хараахан объеĸт үүсгэж байгаа хэрэг биш. Энэ бол объеĸт үүсгэх загварыг тодорхойлж байгаа хэрэг юм. Яг объеĸт үүсгэх явц an = PartyAnimal() мөрөнд явагдана. Өөрөөр хэлбэл PartyAnimal загвараар an гэдэг нэртэй объеĸт үүсгэж байна. Энэ үүссэн объеĸтыг тухайн class-ын instance гэж нэрлэнэ.
Дараагийн мөрүүд нь an объеĸтын party гэсэн методыг дуудан ажиллуулж байна.
PartyAnimal загвараар хэлэн ч instance үүсгэсэн хамаагүй бүгд яг адил загвартай, бүгд дотроо party методтой, тэр метод нь бүгд ижилхэн зүйл хийнэ гэсэн үг. (Манай тохиролдолд x атрибутыг нэгээр нэмэгдүүлж хэвлэх үйлдэл хийдэг.)
PartyAnimal.party(an)
Энэ аргын товчилсон хувилбар нь an.party() гэж ойлгож болно.
So far 1
So far 2
So far 3
So far 4
Бидний мэдэж байгаагаар Python-гийн бүх хувьсагчдад type (төрөл) байдаг. Бид хувьсагчийн чадварыг шалгахын тулд dir( ) фунĸцийг ашиглаж байсан. Бидний бий болгосон class-уудад ч type( ) болон dir( )-ийг ашиглаж болно:
Жишээ нь:
class PartyAnimal:
x = 0
def party(self) :
self.x = self.x + 1
print("So far",self.x)
an = PartyAnimal()
print ("Type", type(an))
print ("Dir ", dir(an))
print ("Type", type(an.x))
print ("Type", type(an.party))
Үр дүн:
Type < class '__main__.PartyAnimal'>
Dir ['__class__', '__delattr__', ...
'__sizeof__', '__str__', '__subclasshook__',
'__weakref__', 'party', 'x']
Type < class 'int'>
Type < class 'method'>
dir-ийн үр дүнг харахад бидний party болон x маань харагдаж байна.
Өмнөх жишээнүүдэд бид class (загвар) тодорхойлж, тухайн class-ын instance (объеĸт)-ийг үүсгэж тэр instance-ийг ашиглаж үзсэн.
Програм ажиллаж дуусахад бүх хувьсагч устгагдна.
Ихэвчлэн бид хувьсагчдийг үүсгэх, устгах талаар төдийлөн боддоггүй ч объеĸтууд маань илүү төвөгтэй болохын хэрээр объеĸтын дотор ямар нэгэн арга хэмжээ авч, тухайн объеĸт үүсч байгаа үед ямар нэгэн зүйлийг тохируулах эсвэл объеĸтыг устгаж байгаа үед ямар нэгэн зүйлийг устгаж цэвэрлэх шаардлагатай болдог.
Хэрэв бид instance үүсгэх, устгах мөчүүдийн талаар объеĸтдоо мэдэгдэхийг хүсч байвал объеĸтдоо тусгайлан нэрлэсэн методуудыг нэмж оруулдаг:
class PartyAnimal:
x = 0
def __init__(self):
print('I am constructed')
def party(self) :
self.x = self.x + 1
print('So far',self.x)
def __del__(self):
print('I am destructed', self.x)
an = PartyAnimal()
an.party()
an.party()
an = 42
print('an contains',an)
Үр дүн:
I am constructed
So far 1
So far 2
I am destructed 2
an contains 42
Эндээс бид an объеĸтын амьдралын мөчлөгийг харж байна.
Объеĸт үүсэнгүүтээ заавал __init__ методыг ажиллуулдаг, харин устгагдахаасаа өмнө заавал __del__ методыг ажиллуулдаг. an = 42 мөр нь an хувьсагчид 42 гэсэн тоог оногдуулснаар байсан объеĸтыг устгаад оронд нь int тоо болгож байна.Ингэж бид объеĸтын амьдралын мөчлөг бүрийг хянаж удирдаж чадаж байна .
Одоогийн байдлаар бид class тодорхойлж, нэг объеĸт бүтээж, тэр объеĸтыг ашиглаад дараа нь объеĸтыг устгасан. Гэхдээ объеĸт хандалтат програмчлалын жинхэнэ хүч нь бид class-ынхаа олон instance бүтээхэд оршдог.
Бид class-ынхаа олон объеĸтыг бүтээхдээ объеĸт тус бүрд өөр өөр анхны утгыг тохируулж болно. Бид объеĸт бүрт өөр өөр анхны утгыг өгөхийн тулд өгөгдлийг constructor-руу дамжуулж болно.
Жишээ нь:
class PartyAnimal:
x = 0
name = ''
def __init__(self, nam):
self.name = nam
print(self.name,'constructed')
def party(self):
self.x = self.x + 1
print(self.name,'party count',self.x)
s = PartyAnimal('Sally')
j = PartyAnimal('Jim')
s.party()
j.party()
s.party()
үр дүн:
Sally constructed
Jim constructed
Sally party count 1
Jim party count 1
Sally party count 2
s = PartyAnimal('Sally') мөр нь s нэртэй instance үүсгэж байна. Дугуй хаалт нь constructor- ыг ажиллуулж байгаа хэрэг юм. Дугуй хаалт доторх параметрийг constructor ажиллахдаа авч ажиллах ёстой. Түүнийг авч ажиллуулах зааварчилгааг init методод зааж өгсөн байна: Гаднаас авсан хувьсагчийг nam гэж түр нэрлээд өөрийн name хувьсанчид оногдуулна.
constructor нь объеĸтын жишээг заадаг self параметр болон объеĸтыг бүтээх явцад байгуулагч руу дамжуулдаг нэмэлт параметрүүдийг хоёуланг нь агуулна.
Объеĸт хандалтат програмчлалын өөр нэг хүчирхэг шинж чанар бол одоо байгаа class-ыг өргөтгөх замаар шинэ class үүсгэх чадвар юм. class-аа өргөтгөхдөө бид анхны class-ыг parent class, шинэ class-ыг child class гэж нэрлэдэг.
Энэ жишээний хувьд бид PartyAnimal class-аа тусдаа файл руу шилжүүлсэн байгаа. Дараа нь бид PartyAnimal class-ыг шинэ файлруу "импортлож" дараах байдлаар өргөтгөж болно:
from party import PartyAnimal
class CricketFan(PartyAnimal):
points = 0
def six(self):
self.points = self.points + 6
self.party()
print(self.name,"points",self.points)
s = PartyAnimal("Sally")
s.party()
j = CricketFan("Jim")
j.party()
j.six()
print(dir(j))
Бид CricketFan class-ыг тодорхойлохдоо PartyAnimal class-ыг өргөжүүлж байгааг харж болно. Энэ нь PartyAnimal class-ын бүх (x) хувьсагч болон (party) методууд нь CricketFan class-д удамшсан гэсэн үг юм. Жишээлбэл, CricketFan class-ын six нэртэй методын хүрээнд бид PartyAnimal ангиас party методыг дуудаж байна.
Програмыг ажиллуулах явцад бид PartyAnimal болон CricketFan-ийн бие даасан instance болгон s болон j-г үүсгэв. j объеĸт нь s объеĸтоос илүү нэмэлт боломжуудтай үүсгэгдсэн.
Sally constructed
Sally party count 1
Jim constructed
Jim party count 1
Jim party count 2
Jim points 6
['__class__', '__delattr__', ... '__weakref__',
'name', 'party', 'points', 'six', 'x']
j объеĸтын (CricketFan class instance) dir гаралтаас харвал бид энэ нь parent class-ын атрибут болон методуудаас гадна CricketFan class үүсэхэд нэмэгдсэн атрибут, методуудтай болохыг харж байна.