Python第三周

面向?qū)ο蟮倪M(jìn)階

包裝器:@property(getter)、@setter

之前我們討論過Python中屬性和方法訪問權(quán)限的問題,雖然我們不建議將屬性設(shè)置為私有的,但是如果直接將屬性暴露給外界也是有問題的,比如我們沒有辦法檢查賦給屬性的值是否有效。我們之前的建議是將屬性命名以單下劃線開頭,通過這種方式來暗示屬性是受保護(hù)的,不建議外界直接訪問,那么如果想訪問屬性可以通過屬性的getter(訪問器)和setter(修改器)方法進(jìn)行對(duì)應(yīng)的操作。如果要做到這點(diǎn),就可以考慮使用@property包裝器來包裝getter和setter方法,使得對(duì)屬性的訪問既安全又方便

__ slots __方法

如果需要限定自定義類型的對(duì)象只能綁定某些屬性,可以通過在類中定義slots變量來進(jìn)行限定。需要注意的是slots的限定只對(duì)當(dāng)前類的對(duì)象生效,對(duì)子類并不起任何作用

class Person(object):

    # 限定Person對(duì)象只能綁定_name, _age和_gender屬性
    __slots__ = ('_name', '_age', '_gender')

    def __init__(self, name, age):
        self._name = name
        self._age = age

    @property
    def name(self):
        return self._name

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, age):
        self._age = age

    def play(self):
        if self._age <= 16:
            print('%s正在玩飛行棋.' % self._name)
        else:
            print('%s正在玩斗地主.' % self._name)


def main():
    person = Person('王大錘', 22)
    person.play()
    person._gender = '男'
    # AttributeError: 'Person' object has no attribute '_is_gay'
    # person._is_gay = True

靜態(tài)方法和類方法

靜態(tài)方法:@staticmethod

類方法:@classmethod

類方法的第一個(gè)參數(shù)約定名為cls,它代表的是當(dāng)前類相關(guān)的信息的對(duì)象(類本身也是一個(gè)對(duì)象,有的地方也稱之為類的元數(shù)據(jù)對(duì)象),通過這個(gè)參數(shù)我們可以獲取和類相關(guān)的信息并且可以創(chuàng)建出類的對(duì)象

from math import sqrt


class Triangle(object):

    def __init__(self, a, b, c):
        self._a = a
        self._b = b
        self._c = c

    @staticmethod
    def is_valid(a, b, c):
        return a + b > c and b + c > a and a + c > b

    def perimeter(self):
        return self._a + self._b + self._c

    def area(self):
        half = self.perimeter() / 2
        return sqrt(half * (half - self._a) *
                    (half - self._b) * (half - self._c))


def main():
    a, b, c = 3, 4, 5
    # 靜態(tài)方法和類方法都是通過給類發(fā)消息來調(diào)用的
    if Triangle.is_valid(a, b, c):
        t = Triangle(a, b, c)
        print(t.perimeter())
        # 也可以通過給類發(fā)消息來調(diào)用對(duì)象方法但是要傳入接收消息的對(duì)象作為參數(shù)
        # print(Triangle.perimeter(t))
        print(t.area())
        # print(Triangle.area(t))
    else:
        print('無法構(gòu)成三角形.')


if __name__ == '__main__':
    main()
from time import time, localtime, sleep


class Clock(object):
    """數(shù)字時(shí)鐘"""

    def __init__(self, hour=0, minute=0, second=0):
        self._hour = hour
        self._minute = minute
        self._second = second

    @classmethod
    def now(cls):
        ctime = localtime(time())
        return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)

    def run(self):
        """走字"""
        self._second += 1
        if self._second == 60:
            self._second = 0
            self._minute += 1
            if self._minute == 60:
                self._minute = 0
                self._hour += 1
                if self._hour == 24:
                    self._hour = 0

    def show(self):
        """顯示時(shí)間"""
        return '%02d:%02d:%02d' % \
               (self._hour, self._minute, self._second)


def main():
    # 通過類方法創(chuàng)建對(duì)象并獲取系統(tǒng)時(shí)間
    clock = Clock.now()
    while True:
        print(clock.show())
        sleep(1)
        clock.run()


if __name__ == '__main__':
    main()

類之間的關(guān)系

1:is-a關(guān)系也叫繼承或泛化,比如學(xué)生和人的關(guān)系
2:has-a關(guān)系通常稱之為關(guān)聯(lián),比如汽車和引擎的關(guān)系都屬于關(guān)聯(lián)關(guān)系;關(guān)聯(lián)關(guān)系如果是整體和部分的關(guān)聯(lián),那么我們稱之為聚合關(guān)系;如果整體進(jìn)一步負(fù)責(zé)了部分的生命周期(整體和部分是不可分割的,同時(shí)同在也同時(shí)消亡),那么這種就是最強(qiáng)的關(guān)聯(lián)關(guān)系,我們稱之為合成關(guān)系。
3:use-a關(guān)系通常稱之為依賴,比如司機(jī)有一個(gè)駕駛的行為,其中使用到了汽車,那么司機(jī)和汽車的關(guān)系就是依賴關(guān)系

繼承和多態(tài)

在已有類的基礎(chǔ)上創(chuàng)建新類,這其中的一種做法就是讓一個(gè)類從另一個(gè)類那里將屬性和方法直接繼承下來,從而減少重復(fù)代碼的編寫。提供繼承信息的我們稱之為父類,也叫超類或基類;得到繼承信息的我們稱之為子類,也叫派生類或衍生類。子類除了繼承父類提供的屬性和方法,還可以定義自己特有的屬性和方法,所以子類比父類擁有的更多的能力,在實(shí)際開發(fā)中,我們經(jīng)常會(huì)用子類對(duì)象去替換掉一個(gè)父類對(duì)象,這是面向?qū)ο缶幊讨幸粋€(gè)常見的行為,對(duì)應(yīng)的原則稱之為里式替換原則,
子類在繼承了父類的方法后,可以對(duì)父類已有的方法給出新的實(shí)現(xiàn)版本,這個(gè)動(dòng)作稱之為方法重寫(override)。通過方法重寫我們可以讓父類的同一個(gè)行為在子類中擁有不同的實(shí)現(xiàn)版本,當(dāng)我們調(diào)用這個(gè)經(jīng)過子類重寫的方法時(shí),不同的子類對(duì)象會(huì)表現(xiàn)出不同的行為,這個(gè)就是多態(tài)

補(bǔ)充

函數(shù)的參數(shù)
必選參數(shù)
默認(rèn)值
可變參數(shù)(args)
關(guān)鍵字參數(shù)(
*kwargs)
命名關(guān)鍵字參數(shù)

  def f1(a,b,c=0,*args,**kw):  
    print(a,b,c,args,kw)  
  
#調(diào)用情況:  
f1(1,2)  
f1(1,2,c=4)  
f1(1,3,6,'aw','wad',x=123,y='1232')  
其中:
a,b 為必選參數(shù)
c=0 為默認(rèn)參數(shù)

*args 為可變參數(shù),可變參數(shù)允許你傳入 0個(gè)或任意個(gè)參數(shù),這些可變參數(shù)在函數(shù)調(diào)用時(shí)自動(dòng)組裝為一個(gè)tuple

**kw 為關(guān)鍵字參數(shù),關(guān)鍵字參數(shù)允許你傳入 0個(gè)或任意個(gè)含參數(shù)名的參數(shù),這些關(guān)鍵字參數(shù)在函數(shù)內(nèi)部自動(dòng)組裝為一個(gè)dict
def person(name,age,*,city='hongkong',job='coder'):  
    print(name,age,city,job)  
person('scofff',212,city='homy',job='eatter') 

后面的兩個(gè)參數(shù)為命名關(guān)鍵字參數(shù)
對(duì)于關(guān)鍵字參數(shù),函數(shù)的調(diào)用者可以傳入任意不受限制的關(guān)鍵字參數(shù),至于到底傳入了哪些,就需要在函數(shù)內(nèi)部通過 kw 檢查。 
與關(guān)鍵字參數(shù)**kw不同,命名關(guān)鍵字參數(shù)需要一個(gè)特殊分隔符*,*后面的參數(shù)被視為命名關(guān)鍵字參數(shù),如果沒有*號(hào),那么后面的參數(shù)將被視為普通的未位置參數(shù)。
命名關(guān)鍵字參數(shù)必須傳入?yún)?shù)名,而命名關(guān)鍵字參數(shù)可以有缺省值,這和位置參數(shù)不同。

面向?qū)ο蟮脑瓌t

單一職責(zé)原則

單一職責(zé)原則的定義是就一個(gè)類而言,應(yīng)該僅有一個(gè)引起他變化的原因。也就是說一個(gè)類應(yīng)該只負(fù)責(zé)一件事情。如果一個(gè)類負(fù)責(zé)了方法M1,方法M2兩個(gè)不同的事情,當(dāng)M1方法發(fā)生變化的時(shí)候,我們需要修改這個(gè)類的M1方法,但是這個(gè)時(shí)候就有可能導(dǎo)致M2方法不能工作。這個(gè)不是我們期待的,但是由于這種設(shè)計(jì)卻很有可能發(fā)生。所以這個(gè)時(shí)候,我們需要把M1方法,M2方法單獨(dú)分離成兩個(gè)類。讓每個(gè)類只專心處理自己的方法。
單一職責(zé)原則的好處如下:
1):可以降低類的復(fù)雜度,一個(gè)類只負(fù)責(zé)一項(xiàng)職責(zé),這樣邏輯也簡(jiǎn)單很多
2):提高類的可讀性,和系統(tǒng)的維護(hù)性,因?yàn)椴粫?huì)有其他奇怪的方法來干擾我們理解這個(gè)類的含義
3):當(dāng)發(fā)生變化的時(shí)候,能將變化的影響降到最小,因?yàn)橹粫?huì)在這個(gè)類中做出修改

開閉原則

開閉原則的定義是軟件中的對(duì)象(類,模塊,函數(shù)等)應(yīng)該對(duì)于擴(kuò)展是開放的,但是對(duì)于修改是關(guān)閉的。
當(dāng)需求發(fā)生改變的時(shí)候,我們需要對(duì)代碼進(jìn)行修改,這個(gè)時(shí)候我們應(yīng)該盡量去擴(kuò)展原來的代碼,而不是去修改原來的代碼,因?yàn)檫@樣可能會(huì)引起更多的問題。
這個(gè)準(zhǔn)則和單一職責(zé)原則一樣,是一個(gè)大家都這樣去認(rèn)為但是又沒規(guī)定具體該如何去做的一種原則。
開閉原則我們可以用一種方式來確保他,我們用抽象去構(gòu)建框架,用實(shí)現(xiàn)擴(kuò)展細(xì)節(jié)。這樣當(dāng)發(fā)生修改的時(shí)候,我們就直接用抽象了派生一個(gè)具體類去實(shí)現(xiàn)修改

里氏替換原則

子類可以去擴(kuò)展父類的功能,但是不能改變父類原有的功能
1.子類可以實(shí)現(xiàn)父類的抽象方法,但是不能覆蓋父類的非抽象方法。
2.子類可以增加自己獨(dú)有的方法。
3.當(dāng)子類的方法重載父類的方法時(shí)候,方法的形參要比父類的方法的輸入?yún)?shù)更加寬松。
4.當(dāng)子類的方法實(shí)現(xiàn)父類的抽象方法時(shí),方法的返回值要比父類更嚴(yán)格。

合成聚合復(fù)用原則

合成/聚合復(fù)用原則經(jīng)常又叫做合成復(fù)用原則。該原則就是在一個(gè)新的對(duì)象里面使用一些已有的對(duì)象,使之成為新對(duì)象的一部分:新的對(duì)象通過向這些對(duì)象的委派達(dá)到復(fù)用已有功能的目的

迪米特法則

迪米特原則也被稱為最小知識(shí)原則
定義為一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象保持最小的了解。
因?yàn)轭惻c類之間的關(guān)系越密切,耦合度越大,當(dāng)一個(gè)類發(fā)生改變時(shí),對(duì)另一個(gè)類的影響也越大,所以這也是我們提倡的軟件編程的總的原則:低耦合,高內(nèi)聚。
使用總結(jié):
(1).在類的劃分上,應(yīng)當(dāng)盡量創(chuàng)建松耦合的類,類之間的耦合度越低,就越有利于復(fù)用,一個(gè)處在松耦合中的類一旦被修改,不會(huì)對(duì)關(guān)聯(lián)的類造成太大波及;
(2).在類的結(jié)構(gòu)設(shè)計(jì)上,每一個(gè)類都應(yīng)當(dāng)盡量降低其成員變量和成員函數(shù)的訪問權(quán)限;
(3).在類的設(shè)計(jì)上,只要有可能,一個(gè)類型應(yīng)當(dāng)設(shè)計(jì)成不變類;
(4).在對(duì)其他類的引用上,一個(gè)對(duì)象對(duì)其他對(duì)象的引用應(yīng)當(dāng)降到最低。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評(píng)論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,497評(píng)論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評(píng)論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,727評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,193評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,411評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,945評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,777評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,978評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,216評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評(píng)論 1 286
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,657評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,960評(píng)論 2 373

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 31,717評(píng)論 18 399
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,782評(píng)論 18 139
  • 一:java概述: 1,JDK:Java Development Kit,java的開發(fā)和運(yùn)行環(huán)境,java的開發(fā)...
    慕容小偉閱讀 1,814評(píng)論 0 10
  • 2 沒關(guān)系,你還有我 發(fā)布1378字 花團(tuán)錦簇,香氣襲人,帝國(guó)這座六星級(jí)酒店里,所有的賓客都把目光放在高臺(tái)上一對(duì)剛...
    媛姐不是吃素的閱讀 450評(píng)論 0 0
  • 最近,有朋友向我咨詢一個(gè)問題:家有四套房,自己住一套,老公有工作,孩子也大了,自己家里呆,租金二十萬,該不該去工作...
    邊緣上的沉思閱讀 3,410評(píng)論 10 14