1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        【Python基礎】Python 面向對象編程(下篇)

        共 1639字,需瀏覽 4分鐘

         ·

        2020-08-09 09:53

        已完成專題

        1我的施工計劃

        2數字專題

        3字符串專題

        4列表專題

        5流程控制專題

        6編程風格專題

        7函數使用

        8.面向對象編程(上篇)

        上一篇面向對象編程(上篇)討論了面向對象編程的基礎部分,使用案例講解了三大特性:封裝、繼承、多態(tài)。

        今天繼續(xù)討論面向對象編程的進階部分

        進階專題

        1 創(chuàng)建抽象方法

        上篇講解多態(tài)部分,定義了基類模塊animals2.py,它里面有一個方法getSpeedBehavior,然后2個繼承類中分別重寫了此方法。雖然這種模式并不會報錯,但卻不是最佳編程寫法。

        class?Animal():
        ???cprop?=?"我是類上的屬性cprop"
        ???
        ???def?__init__(self,name,speed):
        ???????self.name?=?name?#?動物名字
        ???????self._speed?=?speed?#?動物行走或飛行速度
        ??
        ???def?__str__(self):
        ????????return?'''Animal({0.name},{0._speed})?is?printed
        ????????????????name={0.name}
        ????????????????speed={0._speed}'''
        .format(self)

        ???def?getSpeedBehavior(self):
        ???????pass?

        更加優(yōu)秀的做法,顯示的定義基類的此方法為抽象方法,并且明確指名這兩個繼承類需要重寫此方法。

        借助Python內置的abc模塊,使用abstractmethod裝飾器,Animal類的改進版:

        import?abc

        class?Animal():
        ???cprop?=?"我是類上的屬性cprop"
        ???
        ???def?__init__(self,name,speed):
        ???????self.name?=?name?#?動物名字
        ???????self._speed?=?speed?#?動物行走或飛行速度
        ??
        ???def?__str__(self):
        ????????return?'''Animal({0.name},{0._speed})?is?printed
        ????????????????name={0.name}
        ????????????????speed={0._speed}'''
        .format(self)
        ???
        ???#?使用abstractmethod裝飾器后,變?yōu)槌橄蠓椒?/span>
        [email protected]
        ???def?getSpeedBehavior(self):
        ???????pass

        其他類都不改變。以上就是創(chuàng)建抽象類的方法。

        2 檢查屬性取值

        已經在Animal類中定義2個屬性name和_speed:

        class?Animal():
        ???cprop?=?"我是類上的屬性cprop"
        ???
        ???def?__init__(self,name,speed):
        ???????self.name?=?name?#?動物名字
        ???????self._speed?=?speed?#?動物行走或飛行速度

        像這種方法定義的屬性,外界可以對屬性賦任意值,這不是合理的。如下speed參數被賦值為負值,這肯定不合理:

        jiafeimao?=?Cat('jiafeimao',-2,'gray','CatGenre')

        所以一種解決方法便是使用@property,寫法也很簡潔:

        ???#?讀
        ???@property?
        ???def?_speed(self):
        ???????return?self.__speed
        ??#?寫
        ???@_speed.setter
        ???def?_speed(self,val):
        ???????if?val?0:
        ???????????raise?ValueError('speed?value?is?negative')
        ???????self.__speed?=?val

        Cat('jiafeimao',-2,'gray','CatGenre')執(zhí)行時,會進入到@_speed.setter,檢查不滿足,拋出取值異常。

        @property就是給_speed函數增加功能后返回一個更強大的函數,@屬性.setter也是一個函數,裝飾后控制著屬性的寫入操作。

        3 給類添加屬性

        基礎篇說到為實例添加屬性,只對此實例生效,其他屬性還是沒有此屬性。怎樣在外面一次添加屬性后,所有實例都能具有呢。

        答案是為類添加屬性,如下所示,為Cat類增加屬性age后,jiafeimao實例 和jiqimao實例都有了age屬性,且都可被修改:

        if?__name__?==?"__main__":
        ????jiafeimao?=?Cat('jiafeimao',2,'gray','CatGenre')
        ????
        ????Cat.age?=?1
        ????jiafeimao.age?=?3
        ????print(jiafeimao.age)?#?3?
        ????jiqimao?=?Cat('jiqimao',3,'dark','CatGenre')
        ????jiqimao.age?=?5
        ????print(jiqimao.age)?#?5

        這就說明,一次為類添加一個屬性,類的所有實例都會有這個新增的屬性。

        這種雖然寫法便利,但是會帶來副作用,支持動態(tài)添加實際上破壞了類的封裝性,為維護程序帶來不便。同時,如果泛濫使用,屬性過多占用內存就會變大,影響程序的性能。

        4 控制隨意添加屬性

        Python應該意識到上面動態(tài)添加屬性帶來的副作用,因此留出一個系統(tǒng)魔法函數__slots__,以此來控制隨意在外添加屬性。

        使用__slots__,定義這個類只能有哪些屬性,不在這個元組里的屬性添加都會失敗。

        如下這樣做后,控制Student類只能有屬性name和age,不允許添加其他屬性:

        class?Student(object):
        ????__slots__?=?('name',?'age')?#?用tuple定義允許綁定的屬性名稱

        ????def?__init__(self,name,age):
        ????????self.name?=?name
        ????????self.age?=?age


        s?=?Student('xiaoming',100)?#?創(chuàng)建新的實例
        s.score=10

        如下異常:

        5 鏈式調用

        每個對外公開的方法,都返回self,這樣在外面調用時,便能形成一條鏈式調用線,在pyecharts等框架中可以看到這種調用風格。

        class?Student(object):
        ????__slots__?=?('name',?'age')?#?用tuple定義允許綁定的屬性名稱

        ????def?__init__(self,name,age):
        ????????self.name?=?name
        ????????self.age?=?age
        ????
        ????def?set_name(self,val):
        ????????self.name?=?val?
        ????????return?self?
        ????
        ????def?set_age(self,age):
        ????????self.age?=?age?
        ????????return?self
        ????
        ????def?print_info(self):
        ????????print("name:?"+self.name)
        ????????print("age:?"+?str(self.age))
        ????????return?self
        ?
        s?=?Student('xiaoming',100)?#?創(chuàng)建新的實例

        (
        ????s
        ????.set_name('xiaoming1')
        ????.set_age(25)
        ????.print_info()
        )

        關于面向對象編程的進階部分,還有一個重要的設計原則:MixIn 原則,這個我們放到后面在講設計模式時一起討論。

        以上就是面向對象編程的進階部分,原創(chuàng)不易,歡迎三連支持。


        往期精彩回顧





        獲取一折本站知識星球優(yōu)惠券,復制鏈接直接打開:

        https://t.zsxq.com/662nyZF

        本站qq群1003271085。

        加入微信群請掃碼進群(如果是博士或者準備讀博士請說明):

        瀏覽 28
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            无码黄页 | 波多野吉衣三级 | 亚洲AV色综成人网 | 99精品久久久久久久免费看蜜月 | 亚洲婷婷女色 | 曰韩欧美综合在线视频 | 女人荫蒂让男人添舒服 | 一区二区无码免费 | 小受性瘾放荡的np | 成人三级在线视频 |