Python Object-Oriented Programming

Object-Oriented Programming

Мэдээлэлд чиглэсэн программчлал

Энэ бүлгийн гол үр дүн нь объеĸтууд хэрхэн бүтээгдэж, тэдгээр нь хэрхэн ажилладаг, хамгийн чухал нь Python болон Python сангуудаас бидэнд олгогддог объеĸтуудыг хэрхэн үр дүнтэй ашиглах талаар үндсэн ойлголттой болох явдал юм.

Энэ хичээлээр бидний суралцах зүйлс:

  • Using objects
  • Our first Python object
  • Classes as types
  • Object lifecycle
  • Multiple instances
  • Inheritance

Using objects

Объект ашиглах

Одоо эргээд харахад өмнөх хичээлүүдээр бид объеĸтуудыг ашиглаж ирсэн. 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-ийн гайхамшиг, Зохиолч: Чарльз Р. Северэнс
                        
                    

Энэ яагаад чухал вэ?

  1. Давтамж бууруулах: Анги болон объект ашигласнаар ижил төрлийн өгөгдөл болон үйлдлийг нэг газар хадгалж, давхардах кодыг багасгадаг.
  2. Удирдах хялбар: Томоохон програмыг жижиг хэсгүүдэд хуваахад тусалдаг.
  3. Дахин ашиглах: Анги үүсгэсэн тохиолдолд нэг кодыг олон удаа дахин ашиглаж болно.

Our first Python object

бидний анхны 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
                        
                    

Classes as types

Classes as types

Бидний мэдэж байгаагаар 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 маань харагдаж байна.

Object lifecycle

Объектын амьдралын мөчлөг

Өмнөх жишээнүүдэд бид 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 тоо болгож байна.Ингэж бид объеĸтын амьдралын мөчлөг бүрийг хянаж удирдаж чадаж байна .

Multiple instances

Multiple instances (ихэнх тохиолдлууд)

Одоогийн байдлаар бид 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 параметр болон объеĸтыг бүтээх явцад байгуулагч руу дамжуулдаг нэмэлт параметрүүдийг хоёуланг нь агуулна.

Inheritance

Inheritance(Өвлүүлэх)

Объеĸт хандалтат програмчлалын өөр нэг хүчирхэг шинж чанар бол одоо байгаа 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 үүсэхэд нэмэгдсэн атрибут, методуудтай болохыг харж байна.