Python的物件導向特性

來源:互聯網
上載者:User

標籤:參數   內建函數   資料   反射   報錯   UNC   機制   例子   lang   

物件導向的特性一、封裝

  Python不依賴語言的特性去封裝資料,而是通過遵循一定的資料屬性或函數屬性的命名來達到封裝的效果。任何以單底線開頭的名字都應該是內部的、私人的。封裝的意義在內部商務邏輯的資料隱藏。Python真正意義上的封裝是用類的內外訪問來區分的。並且它與Java的private屬性有很大的區別,Python並沒有強制性的拒絕外部類對私人屬性的訪問。換句話說,以單底線或雙底線開頭的私人屬性僅僅只是一種約定。需要注意的是,當我們使用另一個模組的私人屬性在匯入時,不能使用“*”號,只能使用私人屬性的名稱。Python有意義上的封裝層次。

1. 第一層封裝

  使用以單底線開頭的私人屬性。對象在調用時可直接使用“對象名 . 私人屬性名稱”。

2. 第二層封裝

  使用以雙底線開頭的私人屬性。對象在調用時不能直接使用“對象名 . 私人屬性名稱”。需要在雙底線開頭的私人屬性前加上“_類名”,如:“對象名 .  _類名 . 私人屬性名稱”。

3. 四三層封裝

  使用自訂的函數來提供介面。明確區分內外,實現內部商務邏輯的封裝,並像java的setter和getter方法一樣給出外部程式的使用自訂的介面函數,讓該介面函數返回一個值私人的性。但是在程式的設計中一定要清醒的認識到,程式在設計之初不應該被私人屬性所捆版,否則在今後的修改或維護中就會非常的痛苦。只有真正需要封裝的資料才需要封裝。比如員工的工資等重要的資料。

        class Person:            _privateproperty = "以單底線開頭的私人屬性"            __property = "以雙底線開頭的私人屬性"            def __init__(self, name, gender, age):                self.name = name                self.gender = gender                self.age = age            def return_property(self):                return self.__property            def showinfo(self):                print(self.name, self.gender, self.age)                 person = Person("Handy","女",18)        #單底線開頭的私人屬性        print(person._privateproperty)        #雙底線開頭的私人屬性,注意調用方式        print(person._Person__property)

 

 

二、繼承

  Python的繼承與C++的多繼承非常相似,它的繼承關係會被解譯器解釋為一個MRO列表,該MRO列表就是一個簡單的所有基類的線性順序列表。MRO列表的構造是通過一個C3線性化演算法來實現的。Python和java一樣,所有類的最終基類是Object。繼承從某種角度上來講是有害的,繼承將類與類之間耦合到一塊了。這大大的破壞了系統的封閉原則。繼承真正有意義的是介面式的繼承。Python提供的介面式的繼承。

Python 的繼承順序可由類使用__mro__查看。解譯器查看順序遵循以下三條規則:

1. 子類會先於父類被檢查

2. 多個父類會根據他們在列表中的順序進行檢查

3. 如果對下一個類存在兩個合法的選擇,選擇第一個父類

    class Person:        """        描述人的類        """        def __init__(self, name, gender, age):            self.name = name            self.gender = gender            self.age = age        def printinfo(self):            print("人類")    class Student(Person):        """        學生的類        """        def __init__(self, name, gender, age, school):            """            使用super調用父類的建構函式時,參數中不能出現self,因為            super已經預設給出了self,如果此時加上self會報錯。而報錯            的原因是多了一個參數。使用super()調用父類的函數使程式更            加靈活。當然也可以使用以下耦合的調用模式。            Person.__init__(self, name, gender, age)            """            super().__init__(name, gender, age)            self.school = school        def ptintinfo(self):            print(self.name, self.gender, self.age, self.school)    s = Student("Macky", "女", 18, "麻省理工")    s.ptintinfo()

 

 

三、多態

  Python的多態和java的多態一樣。多態的概念指出了對象如何通過他們共有的屬性及函數來訪問,不需要考慮他們之間的具體的類。

    class Person:        def __init__(self, name, age):            self.name = name            self.age = age        def behavior(self):            if self.age >= 0 and self.age <= 18:                print("%s是未成年人"%self.name)            else:                print("%s是成年人"%self.name)    class Adult(Person):        pass    class Pupil(Person):       pass    #實現多態的簡單例子    def func(obj):        obj.behavior()    #初始化Adult和Pupil    adult = Adult("小明",3)    pupil = Pupil("小華",20)    #調用func函數    func(adult)    func(pupil)

 

 

四、反射

  反射的概念是由Smith在1982年首次提出的,主要是指程式可以訪問、檢測和修改它本身狀態或行為的一種能力(自省)。這一概念的提出很快引發了電腦科學領域關於應用反射性的研究。它首先被程式語言的設計領域所採用,並在Lisp和物件導向方面取得了成績。反射展示了某對象在運行期間是如何取得自己的狀態的。如果傳一個對象給你,你可以查出他的所有能力,這是一項強大的特性。如果Python不支援某種形式的反射功能,dir和type內建函數,將很難工作。還有那些特殊的屬性,像__dict__、__name__及__doc__。那反射究竟有什麼好處呢?它可以事先定義好介面,介面只有在被完成後才會真正執行,這實現了隨插即用,這其實是一種“後期綁定”,你可以事先把主要的邏輯寫好(只定義介面),然後後期再去實現介面的功能。這與Java的反射機制是一樣的,只不過在變現形式上不同。在開發中這項技術是必不可少的。

反射技術的實現基於以下四個函數:

   hasattr(object, name)                                  

  判斷object中有沒有一個name字串對應的方法或屬性。

   getattr(object, name, default=None)         

  擷取對象的屬性值或這函數的地址。當擷取對象的屬性值不存在時返回False,而函數不存在時報錯。如果要想函數不存在時不報錯能並且能通知我們函數不存在,惡可以使用default參數。該函數的功能與對象調用屬性相同。如:getattr(x, ‘y‘)   <==>   x.y

   setattr(x, y, v)                                               

  為對象x的屬性y設定或修改一個值,當屬性不存在時,會將setattr設定的不存在的屬性向對象的字典中追加。如:setattr(x, y, v)   <==>   x.y =v

   delattr(x, y)                                                   

  刪除對象的屬性。如:delattr(x, y)   <==>   del x.y

    class Person:        def __init__(self, name, gender, age):            self.name = name            self.gender = gender            self.age = age        def eating(self):            print("在吃飯")        def sleep(self):            print("在睡覺")    person = Person("Handy","女",18)    #使用hasattr判斷對象中是否存在屬性name    print(hasattr(person, "name"))  #輸出:True    #使用getattr擷取對象的屬性值    print(getattr(person, "name"))  #輸出:Handy    #使用getattr擷取對象的函數地址    print(getattr(person, "eating"))#輸出:eatting()的地址    #運行函數    getattr(person, "eating")()     #輸出:在吃飯    #使用getattr的default參數    print(getattr(person, "eatingfood", "函數不存在"))    #輸出:函數不存在    #使用setattr修改一個值    setattr(person, "name", "Lily")    print(person.__dict__)    #向對象的字典追加一個不存在的值    setattr(person, "ID", "001")    print(person.__dict__)    #增加函數1    setattr(person, "func", lambda x : x+1)    print(person.func)    print(person.func(10))    #增加函數2    setattr(person, "func", lambda self : self.name+"是可以這樣做的")    print(person.func)    print(person.func(person))    #使用delattr刪除對象的屬性    delattr(person, "ID")    print(person.__dict__)

 

Python的物件導向特性

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.