<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【Python基礎(chǔ)】Python 面向?qū)ο缶幊?上篇)

          共 8574字,需瀏覽 18分鐘

           ·

          2020-08-09 09:53


          我的施工計(jì)劃圖

          已完成專題包括:

          1我的施工計(jì)劃

          2數(shù)字專題

          3字符串專題

          4列表專題

          5流程控制專題

          6編程風(fēng)格專題

          7函數(shù)使用專題

          今天是面向?qū)ο缶幊痰纳掀夯A(chǔ)專題

          Python 面向?qū)ο缶幊?/span>

          面向?qū)ο蟪绦蛟O(shè)計(jì)思想,首先思考的不是程序執(zhí)行流程,它的核心是抽象出一個(gè)對(duì)象,然后構(gòu)思此對(duì)象包括的數(shù)據(jù),以及操作數(shù)據(jù)的行為方法。

          本專題主要討論面向?qū)ο缶幊?OOP)的基礎(chǔ)和進(jìn)階知識(shí),實(shí)際開(kāi)發(fā)模型中OOP的主要實(shí)踐,盡量使用最貼切的例子。

          基礎(chǔ)專題

          1 類定義

          動(dòng)物是自然界一個(gè)龐大的群體,以建模動(dòng)物類為主要案例論述OOP編程。

          Python語(yǔ)言創(chuàng)建動(dòng)物類的基本語(yǔ)法如下,使用class關(guān)鍵字定義一個(gè)動(dòng)物類:

          class?Animal():
          ????pass

          類里面可包括數(shù)據(jù),如下所示的Animal類包括兩個(gè)數(shù)據(jù):self.nameself.speed

          class?Animal():
          ???def?__init__(self,name,speed):
          ???????self.name?=?name?#?動(dòng)物名字
          ???????self.speed?=?speed?#?動(dòng)物行走或飛行速度

          注意到類里面通過(guò)系統(tǒng)函數(shù)__init__為類的2個(gè)數(shù)據(jù)賦值,數(shù)據(jù)前使用self保留字。

          self的作用是指名這兩個(gè)數(shù)據(jù)是實(shí)例上的,而非類上的。

          同時(shí)注意到__init__方法的第一個(gè)參數(shù)也帶有self,所以也表明此方法是實(shí)例上的方法。

          2 實(shí)例

          理解什么是實(shí)例上的數(shù)據(jù)或方法,什么是類上的數(shù)據(jù),需要先建立實(shí)例的概念,的概念,如下:

          #?生成一個(gè)名字叫加菲貓、行走速度8km/h的cat對(duì)象
          cat?=?Animal('加菲貓',8)?

          cat就是Animal的實(shí)例,也可以一次創(chuàng)建成千上百個(gè)實(shí)例,如下創(chuàng)建1000只蜜蜂:

          bees?=?[Animal('bee'+str(i),5)?for?i?in?range(1000)]

          總結(jié):自始至終只使用一個(gè)類Animal,但卻可以創(chuàng)建出許多個(gè)它的實(shí)例,因此是一對(duì)多的關(guān)系。

          實(shí)例創(chuàng)建完成后,下一步打印它看看:

          In?[1]:?print(cat)???????????????????????????????????????????????????????????
          <__main__.Animal?object?at?0x7fce3a596ad0>

          結(jié)果顯示它是Animal對(duì)象,其實(shí)打印結(jié)果顯示實(shí)例屬性信息會(huì)更友好,那么怎么實(shí)現(xiàn)呢?

          3 打印實(shí)例

          只需重新定義一個(gè)系統(tǒng)(又稱為魔法)函數(shù)__str__ ,就能讓打印實(shí)例顯示的更加友好:

          class?Animal():
          ???def?__init__(self,name,speed):
          ???????self.name?=?name?#?動(dòng)物名字
          ???????self.speed?=?speed?#?動(dòng)物行走或飛行速度
          ??
          ???def?__str__(self):
          ????????return?'''Animal({0.name},{0.speed})?is?printed
          ????????????????name={0.name}
          ????????????????speed={0.speed}'''
          .format(self)

          使用0.數(shù)據(jù)名稱的格式,這是類專有的打印格式。

          現(xiàn)在再打印:

          cat?=?Animal('加菲貓',8)
          print(cat)

          打印信息如下:

          Animal(加菲貓,8)?is?printed
          ????????????????name=加菲貓
          ????????????????speed=8

          以上就是想要的打印格式,看到實(shí)例的數(shù)據(jù)值都正確。

          4 屬性

          至此,我們都稱類里的namespeed稱為數(shù)據(jù),其實(shí)它們有一個(gè)專業(yè)名稱:屬性。

          同時(shí),上面還有一個(gè)問(wèn)題我們沒(méi)有回答完全,什么是類上的屬性?

          如下,在最新Animal類定義基礎(chǔ)上,再添加一個(gè)cprop屬性,它前面沒(méi)有self保留字:

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

          類上的屬性直接使用類便可引用:

          In?[1]:?Animal.cprop???????????????????????????????????????????????????????????
          Out[1]:?'我是類上的屬性cprop'

          類上的屬性,實(shí)例同樣可以引用,并且所有的實(shí)例都共用此屬性值:

          In?[1]:?cat?=?Animal('加菲貓',8)
          In?[2]:?cat.cprop??????????????????????????????????????????????????????????????
          Out[2]:?'我是類上的屬性cprop'

          Python作為一門動(dòng)態(tài)語(yǔ)言,支持屬性的動(dòng)態(tài)添加和刪除。

          如下cat實(shí)例原來(lái)不存在color屬性,但是賦值時(shí)不光不會(huì)報(bào)錯(cuò),相反會(huì)直接將屬性添加到cat上:

          cat.color?=?'grap'

          那么,如何驗(yàn)證cat是否有color屬性呢?使用內(nèi)置函數(shù)hasattr

          In?[24]:?hasattr(cat,'color')?#?cat?已經(jīng)有`color`屬性??????????????????????????
          Out[24]:?True

          但是注意:以上添加屬性方法僅僅為cat實(shí)例本身添加,而不會(huì)為其他實(shí)例添加:

          In?[26]:?monkey?=?Animal('大猩猩',2)????????????????????????????????????????????
          In?[27]:?hasattr(monkey,'color')?????????????????????????????????????????????
          Out[27]:?False

          monkey實(shí)例并沒(méi)有color屬性,注意與__init__創(chuàng)建屬性方法的區(qū)別。

          5 private,protected,public

          namespeed屬性,引用此實(shí)例的對(duì)象都能訪問(wèn)到它們,如下:

          #?模塊名稱:manager.py

          import?time

          class?Manager():
          ????def?__init__(self,animal):
          ????????self.animal?=?animal
          ????????
          ????def?recordTime(self):
          ????????self.__t?=?time.time()
          ????????print('feeding?time?for?%s(行走速度為:%s)?is?%.0f'%(self.animal.name,self.animal.speed,self.__t))
          ????
          ????def?getFeedingTime(self):
          ????????return?'%0.f'%(self.__t,)?

          使用以上Manager類,創(chuàng)建一個(gè)cat實(shí)例,xiaoming實(shí)例引用cat:

          cat?=?Animal('加菲貓',8)
          xiaoming?=??Manager(cat)?

          xiaomingrecordTime方法引用里,引用了animal的兩個(gè)屬性namespeed:

          In[1]:?xiaoming.recordTime()

          Out[1]:?feeding?time?for?加菲貓(行走速度為:8)?is?1595681304

          注意看到self.__t屬性,它就是一個(gè)私有屬性,只能被Manager類內(nèi)的所有方法引用,如被方法getFeedingTime方法引用。但是,不能被其他類引用。

          如果我們連speed這個(gè)屬性也不想被其他類訪問(wèn),那么只需將self.speed修改為self.__speed:

          同時(shí)Manager類的self.animal.speed修改為self.animal.__speed,再次調(diào)用下面方法時(shí):

          xiaoming.recordTime()

          就會(huì)報(bào)沒(méi)有__speed屬性的異常,從而驗(yàn)證了__speed屬性已經(jīng)變?yōu)轭悆?nèi)私有,不會(huì)暴露在外面。

          總結(jié):name屬性相當(dāng)于java的public屬性,而__speed相當(dāng)于java的private屬性。

          下面在說(shuō)繼承時(shí),講解protected屬性,實(shí)際上它就是帶有1個(gè)_的屬性,它只能被繼承的類所引用。

          6 繼承

          上面已經(jīng)講完了OOP三大特性中的封裝性,而繼承是它的第二大特性。子類繼承父類的所有publicprotected數(shù)據(jù)和方法,極大提高了代碼的重用性。

          如上創(chuàng)建的Animal類最新版本為:

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

          現(xiàn)在有個(gè)新的需求,要重新定義一個(gè)Cat貓類,它也有namespeed兩個(gè)屬性,同時(shí)還有colorgenre兩個(gè)屬性,打印時(shí)只需要打印namespeed兩個(gè)屬性就行。

          因此,基本可以復(fù)用基類Animal,但需要修改__speed屬性為受保護(hù)(protected)的_speed屬性,這樣子類都可以使用此屬性,而外部還是訪問(wèn)不到它。

          綜合以上,Cat類的定義如下:

          class?Cat(Animal):
          ????def?__init__(self,name,speed,color,genre):
          ????????super().__init__(name,speed)
          ????????self.color?=?color?
          ????????self.genre?=?genre

          首先使用super()方法找到Cat的基類Animal,然后引用基類的__init__方法,這樣復(fù)用基類的方法。

          使用Cat類,打印時(shí),又復(fù)用了基類的 __str__方法:

          jiafeimao?=?Cat('加菲貓',8,'gray','CatGenre')
          print(jiafeimao)

          打印結(jié)果:

          Animal(加菲貓,8)?is?printed
          ????????????????name=加菲貓
          ????????????????speed=8

          以上就是基本的繼承使用案例,繼承要求基類定義的數(shù)據(jù)和行為盡量標(biāo)準(zhǔn)、盡量精簡(jiǎn),以此提高代碼復(fù)用性。

          7 多態(tài)

          如果說(shuō)OOP的封裝和繼承使用起來(lái)更加直觀易用,那么作為第三大特性的多態(tài),在實(shí)踐中真正運(yùn)用起來(lái)就不那么容易。有的讀者OOP編程初期,可能對(duì)多態(tài)的價(jià)值體會(huì)不深刻,甚至都已經(jīng)淡忘它的存在。

          那么問(wèn)題就在:多態(tài)到底真的有用嗎?到底使用在哪些場(chǎng)景?

          多態(tài)價(jià)值很大,使用場(chǎng)景很多,幾乎所有的系統(tǒng)或軟件,都能看到它的應(yīng)用。這篇文章盡可能通過(guò)一個(gè)精簡(jiǎn)的例子說(shuō)明它的價(jià)值和使用方法。如果不用多態(tài),方法怎么寫;使用多態(tài),又是怎么寫。

          為了一脈相承,做到一致性,仍然基于上面的案例,已經(jīng)創(chuàng)建好的Cat類要有一個(gè)方法打印和返回它的爬行速度。同時(shí)需要再創(chuàng)建一個(gè)類Bird,要有一個(gè)方法打印和返回它的飛行速度;

          如果不使用多態(tài),為Cat類新增一個(gè)方法:

          class?Cat(Animal):
          ????def?__init__(self,name,speed,color,genre):
          ????????super().__init__(name,speed)
          ????????self.color?=?color?
          ????????self.genre?=?genre
          ????#?添加方法
          ????def?getRunningSpeed(self):
          ????????print('running?speed?of?%s?is?%s'?%(self.name,?self._speed))
          ????????return?self._speed

          重新創(chuàng)建一個(gè)Bird類:

          class?Bird(Animal):
          ????def?__init__(self,name,speed,color,genre):
          ????????super().__init__(name,speed)
          ????????self.color?=?color?
          ????????self.genre?=?genre
          ????#?添加方法
          ????def?getFlyingSpeed(self):
          ????????print('flying?speed?of?%s?is?%s'?%(self.name,?self._speed))
          ????????return?self._speed

          最后,上面創(chuàng)建的Manager類會(huì)引用CatBird類,但是需要修改recordTime方法,因?yàn)镃at它是爬行的,Bird它是飛行的,所以要根據(jù)對(duì)象類型的不同做邏輯區(qū)分,如下所示:

          #?模塊名稱:manager.py

          import?time
          from?animal?import?(Animal,Cat,Bird)

          class?Manager():
          ????def?__init__(self,animal):
          ????????self.animal?=?animal
          ????????
          ????def?recordTime(self):
          ????????self.__t?=?time.time()
          ????????if?isinstance(self.animal,?Cat):
          ????????????print('feeding?time?for?%s?is?%.0f'%(self.animal.name,self.__t))
          ????????????self.animal.getRunningSpeed()
          ????????if?isinstance(self.animal,Bird):
          ????????????print('feeding?time?for?%s?is?%.0f'%(self.animal.name,self.__t))
          ????????????self.animal.getFlyingSpeed()

          ????def?getFeedingTime(self):
          ????????return?'%0.f'%(self.__t,)?

          如果再來(lái)一個(gè)類,我們又得需要修改recordTime,再增加一個(gè)if分支,從軟件設(shè)計(jì)角度講,這種不斷破壞封裝的行為不可取。

          但是,使用多態(tài),就可以保證recordTime不被修改,不必寫很多if分支。怎么來(lái)實(shí)現(xiàn)呢?

          首先,在基類Animal中創(chuàng)建一個(gè)基類方法,然后CatBird分別重寫此方法,最后傳入到Manager類的animal參數(shù)是什么類型,在recordTime方法中就會(huì)對(duì)應(yīng)調(diào)用這個(gè)animal實(shí)例的方法,這就是多態(tài)。

          代碼如下:

          animal2.py 模塊如下:

          #?animal2.py?模塊

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

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

          class?Cat(Animal):
          ????def?__init__(self,name,speed,color,genre):
          ????????super().__init__(name,speed)
          ????????self.color?=?color?
          ????????self.genre?=?genre
          ????????
          ????#?重寫方法
          ????def?getSpeedBehavior(self):
          ????????print('running?speed?of?%s?is?%s'?%(self.name,?self._speed))
          ????????return?self._speed
          ????????

          class?Bird(Animal):
          ????def?__init__(self,name,speed,color,genre):
          ????????super().__init__(name,speed)
          ????????self.color?=?color?
          ????????self.genre?=?genre

          ????#?重寫方法
          ????def?getSpeedBehavior(self):
          ????????print('flying?speed?of?%s?is?%s'?%(self.name,?self._speed))
          ????????return?self._speed

          manager2.py 模塊如下:

          #?manager2.py?模塊

          import?time
          from?animal2?import?(Animal,Cat,Bird)

          class?Manager():
          ????def?__init__(self,animal):
          ????????self.animal?=?animal
          ????????
          ????def?recordTime(self):
          ????????self.__t?=?time.time()
          ????????print('feeding?time?for?%s?is?%.0f'%(self.animal.name,self.__t))
          ????????self.animal.getSpeedBehavior()

          ????def?getFeedingTime(self):
          ????????return?'%0.f'%(self.__t,)??

          recordTime方法非常清爽,不需要任何if邏輯,只需要調(diào)用我們定義的Animal類的基方法getSpeedBehavior即可。

          在使用上面所有類時(shí),Manager(jiafeimao)傳入Cat類實(shí)例時(shí),recordTime方法調(diào)用就被自動(dòng)指向Cat實(shí)例的getSpeedBehavior方法;

          Manager(haiying)傳入Bird類實(shí)例時(shí),自動(dòng)指向Bird實(shí)例的getSpeedBehavior方法,這就是多態(tài)和它的價(jià)值,Manager類的方法不必每次都修改,保證了類的封裝性。


          if?__name__?==?"__main__":
          ????jiafeimao?=?Cat('jiafeimao',2,'gray','CatGenre')
          ????haiying?=?Bird('haiying',40,'blue','BirdGenre')

          ????Manager(jiafeimao).recordTime()
          ????print('#'*30)
          ????Manager(haiying).recordTime()??

          總結(jié)

          以上就是面向?qū)ο缶幊虒n}的基礎(chǔ)部分,大綱如下:

          • Python 面向?qū)ο缶幊?/p>

          • 基礎(chǔ)專題

            • 1 類定義

            • 2 實(shí)例

            • 3 打印實(shí)例

            • 4 屬性

            • 5 private,protected,public

            • 6 繼承

            • 7 多態(tài)

          • 總結(jié)


          往期精彩回顧





          獲取一折本站知識(shí)星球優(yōu)惠券,復(fù)制鏈接直接打開(kāi):

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

          本站qq群1003271085。

          加入微信群請(qǐng)掃碼進(jìn)群(如果是博士或者準(zhǔn)備讀博士請(qǐng)說(shuō)明):

          瀏覽 34
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  伊人国产在线观看 | 中文字幕永久在线 | 俺也来欧美精品 | 毛毛毛毛毛毛毛片123 | 天天天天天干天天天天天日 |