python開發學習筆記(4)————面向對象編程

面向對象編程

1.面向對象(OOP)

過程:類似函數,只負責執行,而沒有返回值
函數:不僅能執行,還有返回值
定義
面向過程:把某一個需求的所有步驟從頭到尾逐步實現,並將某些功能獨立的代碼封裝成函數,最後完成代碼。
面向過程特點:注重步驟和過程;如果需求複雜,代碼也會複雜;開發複雜項目的難度大。
面向對象:面對需求時,首先明確職責(要做的事情),根據職責確定不同的對象,在對象中封裝不同的方法,最後完成代碼,讓把不同對象調用不同的方法。
面向對象的特點:注重對象和職責;專門應對複雜項目開發,提供固定套路;需要一些面向對象的語法。

2.類和對象
1)定義

類是對一羣具有相同特徵或行爲的事物的統稱,是抽象的,不能直接使用。
特徵稱爲屬性,行爲成爲方法。
類是用來創建對象的。
對象是由類創建出來的一個具體存在,由哪個類創建出來的對象,則具有相應類中的屬性和特徵。

2)類和對象的關係

類是模板,對象是根據類這個模板創建出來的,先有類,再有對象。
類只有一個,對象可以有很多個。不同對象的屬性各不相同。對象的屬性和方法由類決定。

3)類的設計

面向對象開發前,首先進行需求分析,確定程序中需要包含哪些類。
類名:某類事物的名字,滿足大駝峯命名法。每個單詞的首字母都要大寫,單詞與單詞之間沒有下劃線。
屬性:這類事物具有的特徵
方法:這類事物具有的行爲
類名的確定:名詞提煉法,分析整個業務流程,出現的名詞。
屬性和方法的確定:對象的特徵描述通常定義爲屬性,對象具有的行爲,通常定義成方法。

3.面向對象基礎語法
1)dir函數

可以查看對象內所有的屬性及方法
__方法__ 格式的方法是python提供的內置方法/屬性

2)定義簡單的類

1>語法格式:

class 類名:
	def 方法一(self,參數列表):
		pass
	def 方法二(self,參數列表):
		pass

2>創建對象
語法格式:

對象變量 = 類名()
3)引用概念

使用print輸出對象變量,可以輸出這個變量是由哪一個類創建的對象,以及在內存中的地址(十六進制表示)。
定義的變量引用了創建的對象在內存中的地址。
%d 以10進制輸出數字;%x以16進制輸出數字。

4)給對象設置屬性(類外)

可以使用 .屬性名 利用賦值語句即可。但此種方法一般不推薦使用。
self參數:哪一個對象調用的方法,self就是哪一個對象的引用。
所以在類的方法中,使用self.屬性 來調用對象的屬性
***** 對象的屬性也應當封裝在類中

5)初始化方法

創建對象時,自動進行:1.爲對象在內存中分配空間;2.爲對象的屬性設置初始值。
這個設置初始值的方法就是 __init__ 方法。專門定義對象具有哪些屬性。

6)在初始化方法內部設置屬性

self.屬性名 = 屬性的初始值

7)使用參數設置屬性初始值
def __init__(self,參數):
	self.屬性名 = 參數

初始化方法中引入一個形參,將要設置的屬性變爲實參轉入
步驟:
1>把希望設置的屬性值,定義成__init__方法的參數
2>在方法內部,使用self.屬性=形參 接收外部傳遞的參數
3>創建對象時,使用 類名(屬性1,屬性2,…)調用

8)其他內置方法和屬性

1>del方法
當創建對象時,爲對象分配完空間後,自動調用__init__方法。當對象被從內存中銷燬時前,會自動調用__del__方法
2>str方法
print輸出對象變量時,會輸出這個對象變量是由哪個類創建,以及在內存中的地址。
使用__str__方法,可以自定義打印的內容。
語法結構:
在類中定義一個方法

def __str__(self):
		return 要返回的內容(返回的內容必須是字符串)

實際開發有多個類時,先開發簡單的類,或者一個類被另一個類調用,則開發被調用的類。

9)一個對象的屬性可以是另一個類創建的對象

士兵突擊實例

10)身份運算符

身份運算符用於比較兩個對象的內存地址是否一致(是否是對同一對象的引用)

is  x is y,類似id(x)==id(y)
is not  x is not y,類似id(x)!=id(y)

is和 == 的區別
is 判斷的是兩個變量引用對象是否是同一個
==判斷的是引用變量的值是否相等

11)私有屬性和私有方法

1>定義
只能在對象的內部被使用,而不能在外部被訪問到。
在屬性名或方法名前增加兩個下劃線,定義的就是私有屬性或方法。
在對象的一般方法內部,是可以訪問對象的私有屬性的。
2>僞私有屬性和私有方法
python中,並沒有真正意義的私有。
python中,私有屬性的真正名字爲 _類名__私有屬性名, 在外部通過這個屬性名即可直接調用該私有屬性。
python中,私有方法的真正名字爲 _類名__私有方法名, 在外部通過這個方法名即可直接調用該私有方法。
日常開發中,不要使用這種方法訪問對象的私有屬性或私有方法。

4.繼承(相同的代碼不需要複寫)

面向對象三大特性:封裝、繼承、多態

1)單繼承

定義:子類擁有父類的所有屬性和方法
語法格式:

class 子類名(父類名):

專業術語:
例子: Animal 父類, Dog 子類
Dog是Animal的子類,Animal是Dog的父類,Dog類從Animal類繼承
Dog類是Animal類的派生類,Animal類是Dog類的基類,Dog類從Animal類派生。

2)繼承的傳遞性:

C類從B類繼承,B類又從A類繼承。那麼,C類就具有B類和A類的所有屬性和方法。
繼承傳遞性注意事項:

3)方法重寫

當父類的方法實現不能滿足子類需求時,可以對方法進行重寫。
重寫父類方法有兩種情況:
a.覆蓋父類的方法
子類中重新寫父類中的方法,使用子類對象調用方法時,會調用子類中重寫的方法。
方法:在子類中,定義一個和父類同名的方法並且實現
b.對父類方法進行擴展
前提:父類原本封裝的方法實現是子類方法的一部分
方法:在子類中重寫父類的方法;在需要的位置使用super().父類方法,來調用父類方法的執行;代碼其他的位置針對子類的需求,編寫子類特有的代碼實現。
關於super:
python中,super是一個特殊的類;super()就是使用super類創建出來的對象;最常使用的場景就是在重寫父類方法時,調用在父類中封裝的方法實現。
調用父類方法的另外一種方式(python2.x)
父類名.方法(self)
python3.x 也支持,但是不推薦這樣調用,因爲父類一旦發生改變,這裏也需要修改。

5.私有屬性和私有方法(繼承方面)

1)子類不能在自己的方法內部直接訪問父類的私有屬性或私有方法
2)子類對象可以通過父類的公有方法間接訪問私有屬性或私有方法

6.多繼承
1)概念

子類可以擁有多個父類,並且擁有所有父類的屬性和方法
語法:

class 子類名(父類名1,父類名2,……):
	pass
2)注意事項

a.如果不同父類中存在同名的方法,子類對象在調用方法時,會調用某一類中的方法。在實際開發中要避免這種情況,父類之間存在同名方法時,應該儘量避免使用多繼承。
科普:python中的MRO----方法搜索順序
MRO是 方法解決順序,主要用於在多繼承時判斷方法、屬性的調用路徑。
python中內置屬性__mro__可以查看方法搜索順序。
如,print(c.__mro__)會輸出c對象的所有關係類,輸出順序則爲方法的搜索順序。找到相應方法就執行,沒有找到就繼續向下搜索。

3)新式類與舊式類(經典類)

object是python爲所有對象提供的基類。
新式類:以object類爲基類,推薦使用。
經典類:不以object類爲基類,不推薦使用。
python3.x中定義的類默認都是新式類。
python2.x中,如果沒有指定父類,則不會以object爲基類。
爲了編寫的代碼在python2.x和python3.x中都能運行,建議今後定義類時,如果沒有父類,統一繼承自object。

class 類名(object):
		pass
7.多態

不同的子類對象調用相同的父類方法,產生不同的執行結果。
特點:增加代碼的靈活度;以繼承和重寫父類方法爲前提;調用方法的技巧,不會影響到類的內部設計。

8.類屬性、類方法、靜態方法
1)類結構

術語:創建出來的對象叫類的實例;創建對象的動作叫實例化;對象的屬性叫實例屬性;對象調用的方法叫實例方法。
每個對象都有自己獨立的內存空間,保存各自不同的屬性;多個對象的方法,在內存中只有一份,在調用方法時,需要把對象的引用傳遞到方法內部。

2)類是一個特殊的對象

程序運行時,類會被加載到內存中;python中,類是特殊的對象——類對象;程序運行時,類對象在內存中只有一份,使用一個類可以創建出很多個對象實例;除了封裝實例的屬性和方法外,類對象還可以擁有自己的屬性和方法;通過 類名. 的方法可以訪問類的屬性或者類的方法。

3)類屬性和實例屬性

1>類屬性:類對象中定義的屬性;通常用來記錄與這個類相關的特徵;類屬性不會用於記錄具體對象的特徵。
2>屬性的獲取機制
python中屬性的獲取存在一個向上查找機制
步驟:首先在對象內部查找對象屬性;如果沒有找到就會向上尋找類屬性。
一般是 類名.類屬性名 進行調用。對象.類屬性也可以調用,但不推薦。
注意:如果使用 對象.類屬性 = 值 語句時,只會給對象添加一個屬性,而不會影響到類屬性的值。

4)類方法

語法結構:

@classmethod
def 類方法名(cls):
	pass

1>類方法需要用修飾器 @classmethod 來標識,告訴解釋器這是一個類方法
2>類方法的第一個參數應該是cls
由哪一個類調用的方法,方法內的cls就是哪一個類的引用
這個參數和實例方法的第一個參數是self類似
提示使用其他名稱也可以,不過習慣使用cls
3>通過 類名. 調用類方法,調用方法時,不需要傳遞cls參數
4>在方法內部:
可以使用 cls. 訪問類的屬性
也可以通過 cls. 調用其他的類方法
5)靜態方法
場景:開發時,如果需要在類中封裝一個方法,這個方法:既不需要訪問實例屬性或者調用實例方法,也不需要訪問類屬性或調用類方法。這個時候,可以把這個方法封裝成一個靜態方法。
語法:

@staticmethod
def 靜態方法名():
	pass

 靜態方法需要用修飾器 @staticmethod 標識,告訴解釋器這是一個靜態方法
 通過類名,調用靜態方法

6)方法綜合

實例方法:方法內部需要訪問實例屬性;實例方法內部可以使用 類名.訪問類屬性
類方法:方法內部只需要訪問類屬性
靜態方法:方法內部,不需要訪問實例屬性和類屬性

9.單例模式
1)設計模式和單例設計模式

設計模式:前人工作的總結和提煉,通常,設計模式都是針對某一特定問題的成熟的解決方案。使用設計模式爲了可重用代碼、讓代碼更容易地被他人理解、保證代碼可靠性。
單例設計模式:目的:讓類創建的對象,在系統中只有唯一的一個實例。
每一次執行 類名() 返回的對象,內存地址是相同的。

2)__new__方法

1>使用 類名() 創建對象時,python解釋器首先會調用 __new__ 方法爲對象分配空間。
2>__new__是一個由object基類提供的內置的靜態方法,作用有兩個:在內存中爲對象分配空間;返回對象的引用。
3>python解釋器獲得對象的引用後,將引用作爲第一個參數,傳遞給__init__方法
4>重寫__new__方法一定要 return super().__new__(cls)
5>如果不做上一步,python解釋器就得不到分配了空間的對象引用,就不會調用對象的初始化方法。
6>注意:__new__是一個靜態方法,調用時需要主動傳遞cls參數

3)單例設計模式思路分析

1.>定義一個類屬性,初始值是None,用於記錄單例對象的引用
2>重寫__new__方法
3>如果類屬性 is None,調用父類方法分配空間,並在類屬性中記錄結果;如果類屬性 is not None,則直接把類屬性中記錄的對象引用返回。
4>返回類屬性中記錄的對象引用。

class 類名:
instance = None
def __new__(cls, *args, **kwargs):
	if cls.instance is None:   #判斷類屬性是否已經被賦值
		cls.instance = super().__new__(cls)
	return cls.instance    #返回類屬性的單例引用
4)只執行一次初始化工作

上一節中,每次創建新對象,佔用的都是同一個內存地址,即對象引用一直保持不變,但是,初始化方法還會被再次調用。
需求
讓初始化動作只被執行一次。
解決方法:
1>定義一個類屬性 init_flag 標記是否執行過初始化方法,初始值爲False
2>在 __init__ 方法中,判斷init_flag,如果爲False 就執行初始化動作
3>然後將 init_flag 設置爲True
4>這樣,再次自動調用 __init__ 方法時,初始化動作就不會再被執行了。

10.異常

python解釋器遇到錯誤,會停止程序執行,並提供一些列錯誤信息,就是異常。
程序停止執行並且提示錯誤信息,通常稱之爲拋出異常。
通過異常捕捉可以針對突發事件做集中的處理,從而保證程序的穩定性和健壯性。

1)異常捕獲

語法:

try:
	嘗試執行的代碼
except:
	出現錯誤的處理
2)錯誤類型捕獲

捕獲錯誤類型,可以針對不同類型的錯誤,做出不同的響應。
語法:

try:
	嘗試執行的代碼
except 錯誤類型1:
	針對錯誤類型1,對應的代碼處理
except (錯誤類型2,錯誤類型3):
	針對錯誤類型2和3,對應的代碼處理
except Exception as result:
	print(“未知錯誤 %s” % result)

最後一個except 可以捕獲未考慮到的錯誤,這樣,無論出現任何錯誤,程序都不會終止。實際開發中,要預判所有可能出現的錯誤還是有難度的。

3)異常捕獲完整語法
try:
	嘗試執行的代碼
except 錯誤類型1:
	針對錯誤類型1,對應的代碼處理
except (錯誤類型2,錯誤類型3):
	針對錯誤類型2和3,對應的代碼處理
except Exception as result:
	print(“未知錯誤 %s” % result)
else:
	沒有異常纔會執行的代碼
finally:
	無論是否有異常,都會執行的代碼
4)異常的傳遞

當函數/方法執行出現異常,會將異常傳遞給函數/方法調用一方。
如果傳遞到主程序,仍然沒有異常處理,程序纔會被終止。
提示:在開發中,可以在主函數中增加異常捕獲;在主函數中調用其他函數,只要出現異常,都會傳遞到主函數的異常捕獲中;這樣就不需要在代碼中,增加大量的異常捕獲,能夠保證代碼的整潔。

5)拋出raise異常

根據應用程序特有的業務需求主動拋出異常。
比如,提示用戶輸入密碼,如果長度少於8, 拋出異常。
python中提供了一個Exception異常類
步驟:創建一個Exception的對象;使用raise關鍵字拋出異常對象
語法步驟:1>創建異常對象 ex = Exception(“錯誤信息”) 括號內可以輸入錯誤信息。
2>拋出異常 raise ex

11.模塊
1)模塊的兩種導入方式

1>import 導入
如,import 模塊名1
import 模塊名2
每個導入應該獨佔一行
導入之後,使用 模塊名. 使用模塊提供的工具 ——全局變量、函數、類
可以使用as指定模塊的別名
import 模塊名1 as 模塊別名
模塊別名應該符合大駝峯命名法
2>from…import導入
如果希望從某一個模塊中,導入部分工具,就可以使用from…import的方式
import 模塊名 是一次性把模塊中所有工具全部導入,並且通過模塊名/別名訪問
語法:
from 模塊名1 import 工具名
導入之後,不需要通過模塊名;可以直接使用模塊提供的工具——全局變量、函數、類
注意:如果兩個模塊含有同名的函數,後導入模塊的函數會覆蓋先導入的函數。
3>from…import * (知道)
語法:
from 模塊名1 import *

2)模塊的搜索順序

python解釋器在導入模塊時,會:
a. 搜索當前目錄指定模塊名的文件,如果有就直接導入
b. 如果沒有,再搜索系統目錄
開發時,給文件起名,不要和系統的模塊文件重名
python中每一個模塊都有一個內置屬性,__file__可以查看模塊的完整路徑

3)原則———每一個文件都應該是可以被導入的

1>一個獨立的python文件就是一個模塊
2>在導入文件時,文件中所有沒有任何縮進的代碼都會執行一遍
__name__屬性
__name__是python的一個內置屬性,記錄着一個字符串
如果是被其他文件導入的,__name__就是模塊名
如果是當前執行的程序 __name____main__

4)包

1>概念:包含多個模塊的特殊目錄;目錄下有一個特殊的文件__init__.py;包名的命名方式和變量名一致,小寫字母。
2>好處:使用 import 包名 可以一次性導入包中所有的模塊
3>建立包的方式:新建一個包,新建一個名爲__init__.py文件
4>要在外界使用包中的模塊,需要在__init__.py中指定對外界提供的模塊列表
from . import 其他py文件名

5)發佈模塊

1>製作發佈壓縮包步驟
a. 創建setup.py文件
b. 構建模塊
python3 setup.py build
c. 生成發佈壓縮包
python3 setup.py sdist

6)安裝模塊包
tar -zxvf 包名.tar.gz
sudo python3 setup.py install

卸載時,直接從安裝目錄下刪除包即可
12.文件操作

1)文件的概念

1>定義
計算機的文件,就是存儲在長期儲存設備上的一些數據
長期存儲設備包括:硬盤、U盤、移動硬盤、光盤。。。
2>文件的作用
講數據長期保存下來,在需要的時候使用
3>文件的存儲方式
計算機中,文件是以二進制的方式保存在磁盤上的

文本文件:
a。可以使用文本編輯器查看
b。本質上還是二進制文件
c。例如:python源文件
二進制文件:
a。保存的內容不是給人直接閱讀的,而是提供給其他軟件使用的
b。例如:圖片文件、音頻文件、視頻文件等
c。二進制文件不能使用文本編輯器查看
2)文件操作

1>操作文件的步驟:打開文件;讀寫文件;關閉文件
2>操作文件的函數/方法
函數 open 打開文件,並且返回文件操作對象
方法 read 將文件內容讀取到內存
方法 write 將指定內容寫入文件
方法 close 關閉文件
如果忘記關閉文件,就是造成資源的消耗,而且會影響到後續對文件的訪問。
read方法是一次性讀取並返回文件的全部內容
3>文件指針
read方法執行後,會把文件指針移動到文件的末尾。
文件指針標記從哪個位置開始讀取數據
第一次打開文件時,通常文件指針會指向文件的開始位置
當執行了read方法後,文件指針會移動到讀取內容的末尾
4>打開文件的方式
語法:

f = open(“文件名”, “訪問方式”)
r  以只讀方式打開文件,這個默認方式
w  以只寫方式打開文件,如果文件存在則會被覆蓋
a  以追加方式打開文件,如果文件已存在,文件指針將會放在文件的末尾。
r+ 以讀寫方式打開文件,文件的指針將會放在文件的開頭
w+ 以讀寫方式打開文件
a+ 以讀寫方式打開文件,如果文件已存在,文件指針將會放在文件的末尾。如果不存在,創建新文件進行寫入。

5>readline讀取(讀取大文件,避免給內存壓力)
readline方法可以一次讀取一行內容
方法執行後,會把文件指針移動到下一行,準備再次讀取。
6>小文件複製
打開一個文件,讀取所有內容,並寫入到另一個文件中。
7>大文件複製
打開一個文件,逐行讀取內容,並順序寫入另一個文件中
8>文件/目錄的常用管理操作
python中需要導入os模塊

13.文本編碼

python2.x 默認使用 ASCII 編碼
python3.x 默認使用 UTF-8 編碼
ASCII 編碼
計算機中只有256個ASCII字符
一個ASCII在內存中佔用一個字符的空間
UTF-8 編碼
使用1-6個字節表示一個utf-8 字符

1)python2.x中使用中文
# *-* coding:utf-8 *-*
2)python2.x中處理帶中文的字符串

字符串引號前加一個字母u,告訴解釋器這是一個utf-8編碼格式的字符串

14.內建函數eval

eval()函數:將字符串當成有效的表達式來求值並返回計算結果。
注意:不要濫用eval函數,開發時,不要使用eval直接轉換input的結果
__import__(‘os’).system(‘ls’) 其他用戶用這個命令查看本機文件
其他用戶可以通過eval 來操作本機系統

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章