第二部分 面向?qū)ο?/span> 1. 面向?qū)ο?OOP)基本概念 面向?qū)ο缶幊?—— 簡(jiǎn)寫 面向過(guò)程 —— 怎么做? 把完成某一個(gè)需求的 所有步驟 從頭到尾 逐步實(shí)現(xiàn) 根據(jù)開(kāi)發(fā)需求,,將某些 功能獨(dú)立 的代碼 封裝 成一個(gè)又一個(gè) 函數(shù) 最后完成的代碼,,就是順序地調(diào)用 不同的函數(shù) 特點(diǎn): 注重 步驟與過(guò)程,不注重職責(zé)分工 如果需求復(fù)雜,,代碼會(huì)變得很復(fù)雜 開(kāi)發(fā)復(fù)雜項(xiàng)目,,沒(méi)有固定的套路,開(kāi)發(fā)難度很大! 面向?qū)ο?—— 誰(shuí)來(lái)做,? 相比較函數(shù),,面向?qū)ο?是更大的封裝,根據(jù)職責(zé)在 一個(gè)對(duì)象中封裝多個(gè)方法 在完成某一個(gè)需求前,,首先確定 職責(zé) —— 要做的事情(方法) 根據(jù) 職責(zé) 確定不同的 對(duì)象,,在 對(duì)象 內(nèi)部封裝不同的 方法(多個(gè)) 最后完成的代碼,,就是順序地讓 不同的對(duì)象 調(diào)用 不同的方法 特點(diǎn): 注重 對(duì)象和職責(zé),,不同的對(duì)象承擔(dān)不同的職責(zé) 更加適合應(yīng)對(duì)復(fù)雜的需求變化,是專門應(yīng)對(duì)復(fù)雜項(xiàng)目開(kāi)發(fā),,提供的固定套路 需要在面向過(guò)程基礎(chǔ)上,,再學(xué)習(xí)一些面向?qū)ο蟮恼Z(yǔ)法 類名這類事物的名字,滿足大駝峰命名法 屬性這類事物具有什么樣的特征 方法這類事物具有什么樣的行為 類和對(duì)象 類是對(duì)一群具有相同特征 或者 行為 的事物的一個(gè)統(tǒng)稱,,是抽象的,,特征 被稱為屬性,行為 被稱為方法,。 對(duì)象是 由類創(chuàng)建出來(lái)的一個(gè)具體存在,,是類的實(shí)例化。 在程序開(kāi)發(fā)中,,要設(shè)計(jì)一個(gè)類,,通常需要滿足一下三個(gè)要素: 2. 面向?qū)ο蠡A(chǔ)語(yǔ)法 2.1 dir 內(nèi)置函數(shù)和內(nèi)置方法 在 Python 中對(duì)象幾乎是無(wú)所不在的,我們之前學(xué)習(xí)的變量,、數(shù)據(jù),、函數(shù)都是對(duì)象。 在 Python 中可以使用以下兩個(gè)方法驗(yàn)證: 在 后輸入一個(gè)點(diǎn) ,,然后按下 鍵,,iPython 會(huì)提示該對(duì)象能夠調(diào)用的方法列表。 使用內(nèi)置函數(shù) 傳入 ,,可以查看對(duì)象內(nèi)的所有屬性及方法,。 提示格式的方法是 Python 提供的 。 提示利用好 函數(shù),,在學(xué)習(xí)時(shí)很多內(nèi)容就不需要死記硬背了,。 2.2 定義簡(jiǎn)單的類(只包含方法) 面向?qū)ο笫歉蟮姆庋b,在 一個(gè)類中封裝多個(gè)方法,,這樣通過(guò)這個(gè)類創(chuàng)建出來(lái)的對(duì)象,,就可以直接調(diào)用這些方法了! 定義一個(gè)只包含方法的類: 方法的定義格式和之前學(xué)習(xí)過(guò)的函數(shù)幾乎一樣,,區(qū)別在于第一個(gè)參數(shù)必須是 ,。 注意:類名的 命名規(guī)則 要符合大駝峰命名法。 當(dāng)一個(gè)類定義完成之后,要使用這個(gè)類來(lái)創(chuàng)建對(duì)象,,語(yǔ)法格式如下: 在面向?qū)ο箝_(kāi)發(fā)中,,引用的概念是同樣適用的! 使用 輸出 對(duì)象變量,,默認(rèn)情況下,,是能夠輸出這個(gè)變量 引用的對(duì)象 是 由哪一個(gè)類創(chuàng)建的對(duì)象,以及 在內(nèi)存中的地址(十六進(jìn)制表示),。 提示:在計(jì)算機(jī)中,,通常使用 十六進(jìn)制 表示 內(nèi)存地址。 如果在開(kāi)發(fā)中,,希望使用 輸出 對(duì)象變量 時(shí),,能夠打印自定義的內(nèi)容,就可以利用 這個(gè)內(nèi)置方法了: 注意:方法必須返回一個(gè)字符串,。 2.3 方法中的 self 參數(shù) 在 Python 中,,要 給對(duì)象設(shè)置屬性,非常的容易,,只需要在類的外部的代碼中直接通過(guò) 設(shè)置一個(gè)屬性即可,,但是不推薦使用: 因?yàn)椋簩?duì)象屬性的封裝應(yīng)該封裝在類的內(nèi)部 由哪一個(gè)對(duì)象調(diào)用的方法,方法內(nèi)的 就是哪一個(gè)對(duì)象的引用 在類封裝的方法內(nèi)部,, 就表示當(dāng)前調(diào)用方法的對(duì)象自己,,在方法內(nèi)部: 可以通過(guò) 訪問(wèn)對(duì)象的屬性,也可以通過(guò) 調(diào)用對(duì)象的其他方法,。 調(diào)用方法時(shí),,程序員不需要傳遞 self 參數(shù),。 在 類的外部,通過(guò)訪問(wèn)對(duì)象的 屬性和方法 在 類封裝的方法中,通過(guò) 訪問(wèn)對(duì)象的 屬性和方法 2.4 初始化方法: 當(dāng)使用 創(chuàng)建對(duì)象時(shí),,會(huì) 自動(dòng) 執(zhí)行以下操作: 為對(duì)象在內(nèi)存中分配空間—— 創(chuàng)建對(duì)象 為對(duì)象的屬性設(shè)置初始值—— 初始化方法() 方法是專門用來(lái)定義一個(gè)類具有哪些屬性的方法,! 在 方法內(nèi)部使用 就可以定義屬性,,定義屬性之后,,再使用 類創(chuàng)建的對(duì)象,都會(huì)擁有該屬性,。 在開(kāi)發(fā)中,,如果希望在 創(chuàng)建對(duì)象的同時(shí),就設(shè)置對(duì)象的屬性,,可以對(duì) 方法進(jìn)行改造: 把希望設(shè)置的屬性值,,定義成 方法的參數(shù) 在方法內(nèi)部使用 接收外部傳遞的參數(shù) 在創(chuàng)建對(duì)象時(shí),使用 調(diào)用 2.5 私有屬性和私有方法 應(yīng)用場(chǎng)景 在實(shí)際開(kāi)發(fā)中,,對(duì)象的某些屬性或方法可能只希望在對(duì)象的內(nèi)部被使用,,而不希望在外部被訪問(wèn)到 私有屬性就是對(duì)象不希望公開(kāi)的屬性 私有方法就是對(duì)象不希望公開(kāi)的方法 定義方式 在定義屬性或方法時(shí),,在屬性名或者方法名前增加兩個(gè)下劃線,定義的就是私有屬性或方法: 私有屬性和私有方法 偽私有屬性和私有方法 Python 中,,并沒(méi)有 真正意義 的 私有 在給 屬性,、方法 命名時(shí),實(shí)際是對(duì)名稱做了一些特殊處理,,使得外界無(wú)法訪問(wèn)到 處理方式:在 名稱 前面加上 => 提示:在日常開(kāi)發(fā)中,,不要使用這種方式,訪問(wèn)對(duì)象的 私有屬性 或 私有方法,。 3. 封裝,、繼承和多態(tài) 面向?qū)ο笕筇匦裕?/span> 封裝根據(jù) 職責(zé) 將 屬性 和 方法 封裝 到一個(gè)抽象的 類 中 繼承實(shí)現(xiàn)代碼的重用,相同的代碼不需要重復(fù)的編寫 多態(tài)不同的對(duì)象調(diào)用相同的方法,,產(chǎn)生不同的執(zhí)行結(jié)果,,增加代碼的靈活度 3.1 繼承 3.1.1 單繼承 繼承的概念:子類 擁有 父類 以及 父類的父類 中封裝的所有 屬性 和 方法,。 當(dāng) 父類 的方法實(shí)現(xiàn)不能滿足子類需求時(shí),,可以對(duì)方法進(jìn)行重寫(override) 重寫 父類方法有兩種情況: 覆蓋父類的方法:父類的方法實(shí)現(xiàn) 和 子類的方法實(shí)現(xiàn)完全不同 具體的實(shí)現(xiàn)方式,就相當(dāng)于在 子類中 定義了一個(gè) 和父類同名的方法并且實(shí)現(xiàn),。 對(duì)父類方法進(jìn)行擴(kuò)展:子類的方法實(shí)現(xiàn) 中 包含 父類的方法實(shí)現(xiàn) 在子類中 重寫 父類的方法,;在需要的位置使用 來(lái)調(diào)用父類方法的執(zhí)行代碼;其他的位置針對(duì)子類的需求,,編寫 子類特有的代碼實(shí)現(xiàn),。 關(guān)于 super 在 Python 中 是一個(gè) 特殊的類 就是使用 創(chuàng)建出來(lái)的對(duì)象 最常 使用的場(chǎng)景就是在 重寫父類方法時(shí),調(diào)用 在父類中封裝的方法實(shí)現(xiàn) 調(diào)用父類方法的另外一種方式:在 Python 2.x 時(shí),,如果需要調(diào)用父類的方法,,還可以使用以下方式:。目前在 Python 3.x 還支持這種方式,,但不推薦使用,,因?yàn)橐坏?父類發(fā)生變化,方法調(diào)用位置的 類名 同樣需要修改,。 父類的 私有屬性 和 私有方法 子類對(duì)象不能在自己的方法內(nèi)部,,直接訪問(wèn) 父類的 私有屬性 或 私有方法 子類對(duì)象 可以通過(guò) 父類 的公有方法間接訪問(wèn)到 私有屬性 或 私有方法 私有屬性、方法 是對(duì)象的隱私,,不對(duì)外公開(kāi),,外界 以及 子類 都不能直接訪問(wèn) 私有屬性、方法 通常用于做一些內(nèi)部的事情 3.1.2 多繼承 子類 可以擁有多個(gè)父類,,并且具有 所有父類 的 屬性 和 方法,,例如:孩子 會(huì)繼承自己 父親 和 母親 的 特性。 Python 中的 MRO算法(Method Resolution Order) 如果 不同的父類 中存在 同名的方法,,子類對(duì)象 在調(diào)用方法時(shí),,會(huì)調(diào)用 哪一個(gè)父類中的方法呢,? 提示:開(kāi)發(fā)時(shí),應(yīng)該盡量避免這種容易產(chǎn)生混淆的情況,! —— 如果 父類之間 存在 同名的屬性或者方法,,應(yīng)該盡量避免使用多繼承。 Python 中針對(duì) 類 提供了一個(gè) 內(nèi)置屬性 可以查看 方法 搜索順序 在搜索方法時(shí),,是按照mro的輸出結(jié)果 從左至右 的順序查找的 如果在當(dāng)前類中 找到方法,,就直接執(zhí)行,不再搜索 如果 沒(méi)有找到,,就查找下一個(gè)類 中是否有對(duì)應(yīng)的方法,,如果找到,就直接執(zhí)行,,不再搜索 如果找到最后一個(gè)類,,還沒(méi)有找到方法,程序報(bào)錯(cuò) MRO 是 method resolution order —— 方法搜索順序,,主要用于 在多繼承時(shí)判斷 方法,、屬性 的調(diào)用 路徑 新式類與舊式(經(jīng)典)類 新式類:以 為基類的類,推薦使用 經(jīng)典類:不以 為基類的類,,不推薦使用 在 Python 3.x 中定義類時(shí),,如果沒(méi)有指定父類,會(huì)默認(rèn)使用 object作為該類的 基類 —— Python 3.x 中定義的類都是新式類,,在 Python 2.x 中定義類時(shí),,如果沒(méi)有指定父類,則不會(huì)以 object 作為 基類,。 為了保證編寫的代碼能夠同時(shí)在 Python 2.x 和 Python 3.x 運(yùn)行,!今后在定義類時(shí),如果沒(méi)有父類,,建議統(tǒng)一繼承自 object: 是 Python 為所有對(duì)象提供的 基類,,提供有一些內(nèi)置的屬性和方法,可以使用 函數(shù)查看,。 3.2 多態(tài) 面向?qū)ο笕筇匦裕?/span> 封裝 根據(jù) 職責(zé) 將 屬性 和 方法 封裝 到一個(gè)抽象的 類 中 定義類的準(zhǔn)則 繼承 實(shí)現(xiàn)代碼的重用,,相同的代碼不需要重復(fù)的編寫 設(shè)計(jì)類的技巧 子類針對(duì)自己特有的需求,編寫特定的代碼 多態(tài) 不同的 子類對(duì)象 調(diào)用相同的 父類方法,,產(chǎn)生不同的執(zhí)行結(jié)果 增加代碼的靈活度 以 繼承 和 重寫父類方法 為前提 調(diào)用方法的技巧,,不會(huì)影響到類的內(nèi)部設(shè)計(jì) 多態(tài) 更容易編寫出出通用的代碼,做出通用的編程,,以適應(yīng)需求的不斷變化,! 案例: 在 Dog 類中封裝方法 game:普通狗只是簡(jiǎn)單的玩耍 定義 XiaoTianDog 繼承自 Dog,并且重寫 game 方法:哮天犬需要在天上玩耍 定義 Person 類,,并且封裝一個(gè) 和狗玩 的方法:在方法內(nèi)部,,直接讓 狗對(duì)象 調(diào)用 game 方法 多態(tài)示例 Person 類中只需要讓 狗對(duì)象 調(diào)用 game 方法,,而不關(guān)心具體是 什么狗。 4. 類屬性和類方法 4.1 類的結(jié)構(gòu) 通常會(huì)把: 創(chuàng)建出來(lái)的 對(duì)象 叫做類的實(shí)例 創(chuàng)建對(duì)象的 動(dòng)作 叫做實(shí)例化 對(duì)象的屬性 叫做實(shí)例屬性 對(duì)象調(diào)用的方法 叫做實(shí)例方法 每一個(gè)對(duì)象 都有自己獨(dú)立的內(nèi)存空間,,保存各自不同的屬性 多個(gè)對(duì)象的方法,,在內(nèi)存中只有一份,在調(diào)用方法時(shí),,需要把對(duì)象的引用傳遞到方法內(nèi)部 各個(gè)不同的屬性,,獨(dú)一份的方法 在 Python 中,類是一個(gè)特殊的對(duì)象,。 Python 中 一切皆對(duì)象: class AAA: 定義的類屬于類對(duì)象 obj1 = AAA() 屬于實(shí)例對(duì)象 在程序運(yùn)行時(shí),,類同樣會(huì)被加載到內(nèi)存 在程序運(yùn)行時(shí),類對(duì)象在內(nèi)存中只有一份,,使用 一個(gè)類可以創(chuàng)建出很多個(gè)對(duì)象實(shí)例 除了封裝實(shí)例的屬性和方法外,,類對(duì)象還可以擁有自己的屬性和方法——類屬性、類方法,,通過(guò) 的方式可以 訪問(wèn)類的屬性 或者 調(diào)用類的方法 類的結(jié)構(gòu) 4.2 類屬性和實(shí)例屬性 類屬性 就是類對(duì)象中定義的屬性 通常用來(lái)記錄與這個(gè)類相關(guān)的特征 類屬性不會(huì)用于記錄具體對(duì)象的特征 示例: 定義一個(gè) 工具類,,每件工具都有自己的 : 需求—— 知道使用這個(gè)類,創(chuàng)建了多少個(gè)工具對(duì)象,? 屬性的獲取機(jī)制 在 Python 中 屬性的獲取 存在一個(gè)向上查找機(jī)制 因此,,要訪問(wèn)類屬性有兩種方式: (不推薦,,因?yàn)槿绻褂? 賦值語(yǔ)句,,只會(huì)給對(duì)象添加一個(gè)屬性,而不會(huì)影響到類屬性的值) 4.3 類方法和靜態(tài)方法 4.3.1 類方法 類屬性 就是針對(duì)類對(duì)象定義的屬性 使用 賦值語(yǔ)句 在 關(guān)鍵字下方可以定義 類屬性 類屬性 用于記錄與這個(gè)類相關(guān)的特征 類方法就是針對(duì)類對(duì)象定義的方法 在類方法內(nèi)部可以直接訪問(wèn)類屬性或者調(diào)用其他的類方法 語(yǔ)法如下 類方法需要用修飾器來(lái)標(biāo)識(shí),,告訴解釋器這是一個(gè)類方法 類方法的第一個(gè)參數(shù)應(yīng)該是 由哪一個(gè)類調(diào)用的方法,,方法內(nèi)的 就是哪一個(gè)類的引用 這個(gè)參數(shù)和實(shí)例方法的第一個(gè)參數(shù)是 類似 提示使用其他名稱也可以,不過(guò)習(xí)慣使用 通過(guò)類名.調(diào)用類方法,,調(diào)用方法時(shí),,不需要傳遞 參數(shù) 在方法內(nèi)部 可以通過(guò)訪問(wèn)類的屬性 也可以通過(guò)調(diào)用其他的類方法 示例 定義一個(gè)工具類,每件工具都有自己的 需求—— 在類封裝一個(gè) 的類方法,,輸出使用當(dāng)前這個(gè)類,,創(chuàng)建的對(duì)象個(gè)數(shù) 4.3.2 靜態(tài)方法 在開(kāi)發(fā)時(shí),如果需要在類中封裝一個(gè)方法,,這個(gè)方法: 既不需要訪問(wèn)實(shí)例屬性或者調(diào)用實(shí)例方法 也不需要訪問(wèn)類屬性或者調(diào)用類方法 這個(gè)時(shí)候,,可以把這個(gè)方法封裝成一個(gè)靜態(tài)方法 語(yǔ)法如下 靜態(tài)方法需要用修飾器來(lái)標(biāo)識(shí),告訴解釋器這是一個(gè)靜態(tài)方法 通過(guò)類名.調(diào)用靜態(tài)方法 示例: 靜態(tài)方法 顯示游戲幫助信息 類方法 顯示歷史最高分 實(shí)例方法 開(kāi)始當(dāng)前玩家的游戲 探索: 實(shí)例方法 —— 方法內(nèi)部需要訪問(wèn) 實(shí)例屬性 實(shí)例方法 內(nèi)部可以使用 類名. 訪問(wèn)類屬性 類方法 —— 方法內(nèi)部只需要訪問(wèn) 類屬性 靜態(tài)方法 —— 方法內(nèi)部,,不需要訪問(wèn) 實(shí)例屬性 和 類屬性 5. 單例 5.1 單例設(shè)計(jì)模式 設(shè)計(jì)模式 設(shè)計(jì)模式是前人工作的總結(jié)和提煉,,通常,被人們廣泛流傳的設(shè)計(jì)模式都是針對(duì)某一特定問(wèn)題的成熟的解決方案 使用設(shè)計(jì)模式是為了可重用代碼,、讓代碼更容易被他人理解,、保證代碼可靠性 單例設(shè)計(jì)模式 目的—— 讓類創(chuàng)建的對(duì)象,,在系統(tǒng)中只有唯一的一個(gè)實(shí)例 每一次執(zhí)行 返回的對(duì)象,內(nèi)存地址是相同的 單例設(shè)計(jì)模式的應(yīng)用場(chǎng)景 音樂(lè)播放對(duì)象 回收站對(duì)象 打印機(jī)對(duì)象 …… 5.2 靜態(tài)方法: 使用類名()創(chuàng)建對(duì)象時(shí),, 的解釋器首先會(huì) 調(diào)用 方法為對(duì)象分配空間 是一個(gè) 由 基類提供的內(nèi)置的靜態(tài)方法,,主要作用有兩個(gè): 返回對(duì)象的引用 在內(nèi)存中為對(duì)象分配空間 的解釋器獲得對(duì)象的引用后,將引用作為第一個(gè)參數(shù),,傳遞給 方法 重寫 方法 的代碼非常固定,! 重寫 方法一定要,否則 Python 的解釋器得不到分配了空間的對(duì)象引用,,就不會(huì)調(diào)用對(duì)象的初始化方法 注意: 是一個(gè)靜態(tài)方法,,在調(diào)用時(shí)需要主動(dòng)傳遞參數(shù) 5.3 Python 中的單例 單例—— 讓類創(chuàng)建的對(duì)象,在系統(tǒng)中只有唯一的一個(gè)實(shí)例 定義一個(gè)類屬性,,初始值是 ,,用于記錄單例對(duì)象的引用 重寫 方法 如果類屬性,調(diào)用父類方法分配空間,,并在類屬性中記錄結(jié)果 返回類屬性中記錄的對(duì)象引用 只執(zhí)行一次初始化工作 在每次使用 創(chuàng)建對(duì)象時(shí),, 的解釋器都會(huì)自動(dòng)調(diào)用兩個(gè)方法: 分配空間 對(duì)象初始化 在對(duì) 方法改造之后,每次都會(huì)得到第一次被創(chuàng)建對(duì)象的引用 但是:初始化方法還會(huì)被再次調(diào)用 需求 讓初始化動(dòng)作只被執(zhí)行一次 解決辦法 定義一個(gè)類屬性 標(biāo)記是否執(zhí)行過(guò)初始化動(dòng)作,,初始值為 在 方法中,,判斷 ,如果為 就執(zhí)行初始化動(dòng)作 然后將 設(shè)置為 這樣,,再次自動(dòng)調(diào)用 方法時(shí),,初始化動(dòng)作就不會(huì)被再次執(zhí)行了 Tips 1、Python 能夠自動(dòng)的將一對(duì)括號(hào)內(nèi)部的代碼連接在一起: 2,、一個(gè)對(duì)象的 屬性 可以是 另外一個(gè)類創(chuàng)建的對(duì)象,。 3、在方法中定義類的屬性時(shí),,如果 不知道設(shè)置什么初始值,,可以設(shè)置為 ): 關(guān)鍵字 表示 什么都沒(méi)有,表示一個(gè)空對(duì)象,,沒(méi)有方法和屬性,,是一個(gè)特殊的常量??梢詫?None 賦值給任何一個(gè)變量,。 在 Python 中針對(duì) 比較時(shí),建議使用 判斷 4,、eval() 函數(shù)十分強(qiáng)大 —— 將字符串 當(dāng)成 有效的表達(dá)式 來(lái)求值 并 返回計(jì)算結(jié)果 在開(kāi)發(fā)時(shí)千萬(wàn)不要使用 eval 直接轉(zhuǎn)換 input 的結(jié)果,,舉個(gè)例子: 看完覺(jué)得小編文章不錯(cuò)的記得關(guān)注小編公眾號(hào)哦,關(guān)注有驚喜,!哈哈 |
|