1/579文件IO文件介紹I/O流流的概念讀寫文件文件備份IO介紹大家應(yīng)該聽說過一句話:“好記性不如爛筆頭”件炉。不僅人的大腦會遺忘事情阔挠,計算機也會如此畏邢,比如一個程序在運行過程中用了九牛二虎之力終于計算出了結(jié)果,試想一下如果不把這些數(shù)據(jù)存放起來柒桑,相比重啟電腦之后谱净,“哭都沒地方哭了”可見窑邦,在把數(shù)據(jù)存儲起來有做么大的價值使用文件 的目的:就是把一些存儲存放起來,可以讓程序下一次執(zhí)行的時候直接使用壕探,而不必重新制作一份冈钦,省時省力文件文件是一些具有永久存儲及特定順序的字節(jié)組成的一個有序的、具有名稱的集合李请。在各種介質(zhì)上(可移動磁盤瞧筛、硬盤、CD 等)存儲的集合數(shù)據(jù)导盅。通常情況下文件按照樹狀目錄進行組織较幌,每個文件都有文件名、文件所在路徑白翻、創(chuàng)建時間乍炉、訪問權(quán)限等屬性绢片。流流提供了連續(xù)的字節(jié)流存儲空間,雖然數(shù)據(jù)實際存儲的位置可能不連續(xù)岛琼,甚至可以分布在多個磁盤上底循,但我們看到的是封裝以后的數(shù)據(jù)結(jié)構(gòu),是連續(xù)的字節(jié)流抽象結(jié)構(gòu)槐瑞。除了和磁盤文件直接相關(guān)的文件流以外熙涤,流有多種類型,流可以分布在網(wǎng)絡(luò)中困檩,內(nèi)存中或者是磁帶中祠挫。換句話說,流是一組有序的悼沿,有起點和終點的字節(jié)集合等舔, 是對計算機中數(shù)據(jù)傳輸?shù)目偡Q或者抽象即數(shù)據(jù)在兩個設(shè)備間的傳輸稱為流,流的本質(zhì)是數(shù)據(jù)傳輸显沈。2/57讀取文件想一想:如果想用word編寫一份簡歷软瞎,應(yīng)該有哪些流程呢逢唤?打開word軟件拉讯,新建一個word文件寫入個人簡歷信息保存文件關(guān)閉word軟件同樣,在操作文件的整體過程與使用word編寫一份簡歷的過程是很相似的打開文件新建立一個文件讀/寫數(shù)據(jù)關(guān)閉文件鳖藕。在python魔慷,使用open函數(shù),可以打開一個已經(jīng)存在的文件著恩,或者創(chuàng)建一個新文件 open(文件名院尔,訪問模式)示例如下: f = open('Python.txt', 'w')close( )示例如下:# 新建一個文件,文件名為:test.txtf = open('test.txt', 'w')# 關(guān)閉這個文件 f.close() # with open語句省略關(guān)閉with open('test.txt', 'w') as f: f.read()使用read(num)可以從文件中讀取數(shù)據(jù)喉誊,num表示要從文件中讀取的數(shù)據(jù)的長度(單位是字節(jié))邀摆,如果沒有傳入num,那么就表示讀取文件中所有的數(shù)據(jù)3/57f = open('python.txt', 'r')content = f.read(5)print(content)print("-"*30)content = f.read()print(content)f.close()注意:如果open是打開一個文件伍茄,那么可以不用寫打開的模式栋盹,即只寫 open('python.txt')就像read沒有參數(shù)時一樣,readlines可以按照行的方式把整個文件中的內(nèi)容進行一次性讀取敷矫,并且返回的是一個列表例获,其中每一行的數(shù)據(jù)為一個元素f = open('python.txt', 'r')content = f.readlines()print(type(content))i=1for temp in content: print("%d:%s"%(i, temp)) i+=1f.close()f = open('python.txt', 'r')content = f.readline()print("1:%s"%content)content = f.readline()print("2:%s"%content)f.close()open模式4/57寫入文件寫數(shù)據(jù)(write)使用write()可以完成向文件寫入數(shù)據(jù)f = open('Test.txt', 'w')f.write('hello world, i am here!')f.close()注意:如果文件不存在那么創(chuàng)建,如果存在那么就先清空曹仗,然后寫入數(shù)據(jù)復(fù)制文件5/57復(fù)制文件#導(dǎo)入os模塊import os#原始路徑榨汤,目標(biāo)路徑def Copy_Files(oriPath,endPath): #判斷路徑是否存在 endPathDir=os.path.dirname(endPath) if not os.path.exists(endPathDir): os.makedirs(endPathDir) #讀取數(shù)據(jù)并寫入數(shù)據(jù) with open(oriPath,"rb") as fr: r=fr.read() with open(endPath,"wb") as fw: fw.write(r)下載文件模擬單線程下載文件6/57#導(dǎo)入os模塊import os#oriPath源路徑 endPath目標(biāo)路徑def Download_Files(oriPath,endPath): #判斷路徑存在 endPathDir=os.path.dirname(endPath) #不存在創(chuàng)建 if not os.path.exists(endPathDir): os.makedirs(endPathDir) #源文件大小 file_size=os.path.getsize(oriPath) #每次讀取大小 readSize=1024 #讀取總和 sumRead=0 #打開源文件和目標(biāo)文件 fr=open(oriPath,"rb") fw = open(endPath, "wb") #循環(huán)讀取 數(shù)據(jù) while True: r = fr.read(readSize) #讀到末尾結(jié)束 if r==b"": break else: sumRead+=readSize fw.write(r) print("%s文件已經(jīng)下載了%0.2f%%"%(os.path.basename(oriPath),sumRead/file_size*100)) #清空緩存區(qū),關(guān)閉流 fr.flush() fw.flush() fr.close() fw.close()Download_Files("E:\\頸椎操_超清.mp4","E:\\abc\\jzc.mp4")7/57序列化與反序列化Python序列化和反序列化通過將對象序列化可以將其存儲在變量或者文件中怎茫,可以保存當(dāng)時對象的狀態(tài)收壕,實現(xiàn)其生命周期的延長。并且需要時可以再次將這個對象讀取出來等恐。Python中有幾個常用模塊可實現(xiàn)這一功能乒疏。pickle模塊示例:import pickle#字典序列化dic = {'age': 23, 'job': 'student'}byte_data = pickle.dumps(dic)# out -> b'\x80\x03}q\x00(X\x03\x00\x00\...'print(byte_data)#字典反序列化obj = pickle.loads(byte_data)print(obj)文件流序列化# 序列化with open('abc.txt', 'wb') as f: dic = {'age': 23, 'job': 'student'} pickle.dump(dic, f)# 反序列化with open('abc.txt', 'rb') as f: aa = pickle.load(f) print(aa) print(type(aa)) #json模塊pickle可以很方便地序列化所有對象糙臼。不過json作為更為標(biāo)8/57準(zhǔn)的格式昼汗,具有更好的可讀性(pickle是二進制數(shù)據(jù))和跨平臺性膀篮。是個不錯的選擇账忘。json使用的四個函數(shù)名和pickle一致晃洒。import jsondic = {'age': 23, 'job': 'student'}dic_str = json.dumps(dic)print(type(dic_str), dic_str)# out:{"age": 23, "job": "student"}dic_obj = json.loads(dic_str)print(type(dic_obj), dic_obj)# out: {'age': 23, 'job': 'student'}
文件流序列化
import json
dic = {'age': 23, 'job': 'student'}
with open('abc.json', 'w', encoding='utf-8') as f:
json.dump(dic, f)
with open('abc.json', encoding='utf-8') as f:
obj = json.load(f)
print(obj)
總結(jié)
了解IO
文件流
讀取文件
寫入文件
復(fù)制文件
下載文件
序列化與反序列化
9/57
本章作業(yè)
模擬簡單的博客
1.賬號注冊垒玲,登陸驗證
2.寫文章损谦,包含【標(biāo)題岖免,作者,時間照捡,內(nèi)容】
3.查詢文章颅湘,列出所有文章及時間
4.可查看其中一篇文章
5.刪除文章
6.修改文章
7.退出系統(tǒng)
10面向?qū)ο?/p>
面向?qū)ο蟾拍畹膶W(xué)習(xí)
面向?qū)ο蠛喗?/p>
對象都沒有,還面向?qū)ο缶幊蹋?/p>
10/57
找到對象栗精,面向她看程序就是面向?qū)ο螅?/p>
11/57
這樣才算面向?qū)ο缶幊搪铩?/p>
面向?qū)ο蟮母拍?/p>
簡單地說 面向?qū)ο缶幊蹋∣bject Oriented Programming)簡稱OOP 就是使我們分析闯参、設(shè)計
和實現(xiàn)一個系統(tǒng)的方法盡可能地接近我們認識一個系統(tǒng)的方法。
描述對象之間的相互作用
面向?qū)ο蟮姆椒òǎ?/p>
面向?qū)ο蟮姆治觯∣OA, Object-Oriented Analysis)
面向?qū)ο蟮脑O(shè)計(OOD, Object-Oriented Design)
面向?qū)ο蟮某绦蛟O(shè)計(OOP, Object-Oriented Program)
面向?qū)ο蠹夹g(shù)主要圍繞以下幾個概念:
對象悲立、抽象數(shù)據(jù)類型鹿寨、類、類型層次(子類)薪夕、繼承性脚草、多態(tài)性。
面向?qū)ο骎S面向過程
面向過程:
過程化設(shè)計先確定算法原献,再確定數(shù)據(jù)結(jié)構(gòu)馏慨;面向過程的程序員習(xí)慣于建立數(shù)據(jù)結(jié)構(gòu)存放數(shù)
據(jù)并定義方法(函數(shù))來操作數(shù)據(jù);
面向?qū)ο螅?/p>
面向?qū)ο缶幊滔却_定數(shù)據(jù)結(jié)構(gòu)姑隅,再確定算法写隶;而面向?qū)ο蟪绦騿T則構(gòu)造對象模型,將數(shù)據(jù)
與方法組織在一起讲仰。
面向?qū)ο蟪绦蛟O(shè)計方法的優(yōu)點
可重用性
可擴展性
可管理性
OOP的四個基本機制
抽象
封裝
繼承與派生
12/57
多態(tài)性
抽象
現(xiàn)實世界=>計算機世界
含義:對具體問題(對象)進行概括慕趴,抽出這一類對象的
公共性質(zhì)并加以描述的過程。
要求:先注意問題的本質(zhì)及描述叮盘,其次是實現(xiàn)過程或細
節(jié)秩贰。
所涉及到的主要內(nèi)容:
數(shù)據(jù)抽象---描述某類對象的屬性或狀態(tài)(對象相互區(qū)別的
物理量);
代碼抽象---描述某類對象的共有的行為特征或具有的功
能柔吼。
如何實現(xiàn)抽象:對問題進行分析毒费,提取其屬性和行為 。
抽象是有選擇性的忽略:
決定什么是重要的愈魏,什么不是
聚焦并依賴于那些重要的
忽略那些不重要的
類
13/57
類
是描述對象的“基本原型”觅玻,它定義一類對象所能擁有的數(shù) 據(jù)和能完成的操作想际。
在面向?qū)ο蟮某绦蛟O(shè)計中,類是程序的基本單元溪厘。
相似的對象可以歸并到同一個類中去胡本,就像傳統(tǒng)語言中的
變量與類型關(guān)系一樣。
程序中的對象是類的一個實例畸悬,是一個軟件單元侧甫,它由一
組結(jié)構(gòu)化的數(shù)據(jù)和在其上的一組操作構(gòu)成。
從程序設(shè)計的角度看蹋宦,類是面向?qū)ο蟪绦蛑凶罨镜某绦騿卧冢悓嵸|(zhì)上定義的是一種數(shù)
據(jù)類型,這種數(shù)據(jù)類型就是對象類型冷冗,我們可以使用類名稱來聲明對象變量
聲明對象變量之后守屉,還不能使用對象,必須創(chuàng)建對象實體之后蒿辙,才能使用對象
狗類的設(shè)計
類名:狗(Dog)
屬性:品種 拇泛、毛色、性別思灌、名字俺叭、 腿兒的數(shù)量
方法(行為/功能):叫 、跑习瑰、咬人绪颖、吃、搖尾巴
14/57
對象
含義:它是具有該類類型的一個特定的個體甜奄,是類的一個
變量。
15/57
現(xiàn)實生活中對象指的是客觀世界的實體窃款;
程序中對象就是一組變量和相關(guān)方法的集合课兄,其中變量表明對象的 狀態(tài),方法表明對象所
具有的行為晨继。
16/57
奔馳汽車=類
奔馳smart=類
張三的那輛奔馳smart=對象
狗=類
大黃狗=類
李四家那只大黃狗=對象
水果=類
蘋果=類
紅蘋果=類
紅富士蘋果=類
我嘴里吃了一半的蘋果=對象
17/57
類的定義
定義一個類烟阐,格式如下:
18/57
class 類名:
方法列表
定義一個Car類:
# 定義類
class Car:
#屬性
brand="瑪莎拉蒂"
# 方法
def Move(self):
print("車正在移動...")
自行車:
數(shù)據(jù)(屬性或者狀態(tài)): 車架尺寸、 車輪尺寸紊扬、 牌子蜒茄、
材料名稱…
操作(方法或者功能): 變速、移動餐屎、 修理…
Windows窗口:
數(shù)據(jù)(屬性或者狀態(tài)): 顏色檀葛、 樣式、 標(biāo)題腹缩、 位置…
操作(方法或者功能): 打開窗口屿聋、 改變大小空扎、 移動位
置…
類屬性與方法
python中,可以根據(jù)已經(jīng)定義的類去創(chuàng)建出一個個對象
創(chuàng)建對象的格式為:
對象名 = 類名()
19/57
創(chuàng)建對象demo:
# 定義類
class Car:
# 品牌
brand="瑪莎拉蒂"
# 顏色
color="粉色"
# 輪子個數(shù)
wheelNum=8
# 方法
def GetCarInfo(self):
print('車輪子個數(shù):%d, 顏色%s'%
(self.wheelNum, self.color))
# 移動
def move(self):
print('車在奔跑...')
# 鳴笛
def toot(self):
print("車在鳴笛...嘟嘟..")
#產(chǎn)生對象:
c=Car()
#調(diào)用對象方法
c.GetCarInfo()
#對象添加屬性
c.carType="suv"
20/57
__init__魔法方法
構(gòu)造魔法方法對象的實例化:
<類名>([<參數(shù)列表>])
將引用指向?qū)嵗?/p>
格式:變量名=<類名>([<參數(shù)列表>])
引用對象的成員變量和調(diào)用對象方法
對象.成員變量
對象.成員方法([參數(shù)列表])
對象的構(gòu)造過程
1.為對象開辟空間润讥;
2.調(diào)用魔法方法初始化转锈;
3.返回對象的引用。
類是對象的模板楚殿,同一個類可以創(chuàng)建多個對象撮慨,每個對象
有各自的內(nèi)存空間,不會互相影響脆粥。
構(gòu)造魔法方法是一類特殊的成員方法甫煞,用于創(chuàng)建類的實例
并初始化對象。
聲明構(gòu)造魔法方法
def __init__(self):
21/57
語句塊
注意:
系統(tǒng)為每個類提供一個默認的無參的構(gòu)造魔法方法冠绢,但當(dāng)
自行聲明了構(gòu)造魔法方法后抚吠,這個默認的無參構(gòu)造方法不
再提供
構(gòu)造構(gòu)造方法無返回值
構(gòu)造方法可以重載
構(gòu)造魔法方法的格式:
def 類名:
#初始化函數(shù),用來完成一些默認的設(shè)定
def __init__(self):
pass
# 定義汽車類
class Car:
def __init__(self, newWheelNum, newColor):
self.wheelNum = newWheelNum
self.color = newColor
def move(self):
print('車在跑弟胀,目標(biāo):夏威夷')
# 創(chuàng)建對象
BMW = Car(4, 'green')
print('車的顏色為:%s'%BMW.color)
print('車輪子數(shù)量為:%d'%BMW.wheelNum)
22/57
Self關(guān)鍵字用法
Self
所謂的self楷力,可以理解為自己可以把self當(dāng)做C++中類里面
的this指針一樣理解,就是對象自身的意思某個對象調(diào)用
其方法時孵户,python解釋器會把這個對象作為第一個參數(shù)傳
遞給self萧朝,所以開發(fā)者只需要傳遞后面的參數(shù)即可
1.指代對象本身
2.訪問當(dāng)前對象的成員(區(qū)分同名的局部變量和成員變量)
__del__魔法方法
析構(gòu)魔法方法聲明為:
def __del__(self):
語句
一個類只有一個__del__方法,沒有返回值夏哭。
程序中的對象有垃圾回收器(garbage collector)自動釋
放检柬,因此實際上__del__并不做釋放托管資源的工作 而是
做非托管資源的釋放工作,除非特殊需要竖配,通常被省略何址。
對象傳遞
23/57
對象作為參數(shù)傳遞
實例:
“老張開車去東北.....”
定義一個人類, 屬性:名字,年齡进胯,性別
行為:開車用爪,需要個車
定義一個汽車類,
屬性:品牌胁镐,顏色偎血,價格,輪子個數(shù)... 行為:駕駛盯漂,需要司機
#定義汽車
class Car:
def __init__(self,brand):
self.brand=brand
def BeDrive(self,p):
print(p.name+"正在開車"+self.brand)
#定義人
class People:
def __init__(self,name):
self.name=name
def Drive(self,c):
c.BeDrive(self)
c=Car("瑪莎拉蒂")
p=People("老張")
#對象傳遞
p.Drive(c)
24/57
抽象練習(xí)題
1.創(chuàng)建一個學(xué)員類颇玷,并設(shè)計三個字段用于表示學(xué)生的成績
(語文、數(shù)學(xué)就缆、英語)帖渠;然后定義一個列表list表示一個班
的學(xué)生(10人),依次輸入每個學(xué)生的信息和成績违崇,輸入
的同時將學(xué)員的每科成績劃分等級(100-90:A 89-80:
B 79-70:C 69-60:D 60以下:E)最后輸出所有學(xué)員的
信息
2.編一個關(guān)于求多個某門功課總分和平均分的程序阿弃。
1.每個學(xué)生信息包括姓名和某門功課成績诊霹。
2.假設(shè)5個學(xué)生。
3.類和對象的處理要合理
3.設(shè)計一個游戲角色類
字段:角色名渣淳、血量脾还、魔法、狀態(tài)
方法:釋放技能 被傷害
要求:設(shè)計要合理
封裝
訪問級別:
完全公開: 變量名 方法名
私有 :__變量名 __方法名()
受保護 :_變量名 _方法名()
默認情況下入愧,Python中的成員函數(shù)和成員變量都是公開的
25/57
(public),在python中沒有類似public,private等關(guān)鍵詞來修
飾成員函數(shù)和成員變量鄙漏。
在python中定義私有變量只需要在變量名或函數(shù)名前加
上 ”__“兩個下劃線,那么這個函數(shù)或變量就是私有的了棺蛛。
(1)_xxx "單下劃線 " 開始的成員變量叫做保護變
量怔蚌,意思是只有類實例和子類實例能訪問到這些變量,
需通過類提供的接口進行訪問旁赊;不能用'from module
import *'導(dǎo)入
(2)__xxx 類中的私有變量/方法名 (Python的函數(shù)
也是對象桦踊,所以成員方法稱為成員變量也行得通。),
" 雙下劃線 " 開始的是私有成員终畅,意思是只有類對象自己
能訪問籍胯,連子類對象也不能訪問到這個數(shù)據(jù)。
(3)__xxx__ 系統(tǒng)定義名字离福,前后均有一個“雙下劃線”
代表python里特殊方法專用的標(biāo)識杖狼,如 __init__()代表
類的構(gòu)造函數(shù)。
class Person:
name="Tony"
#私有屬性
__age=18
__gender="男"
#私有方法
def __Method(self):
pass
26/57
在電子方面妖爷,封裝是指把硅片上的電路管腳蝶涩,用導(dǎo)線接引
到外部接頭處,以便與其它器件連接絮识。
在編程語言方面,封裝即隱藏對象的屬性和實現(xiàn)細節(jié)绿聘,僅對
外公開接口,控制在程序中屬性的讀和修改的訪問級別;將
抽象得到的數(shù)據(jù)和行為(或功能)相結(jié)合笋除,形成一個有機
的整體斜友,也就是將數(shù)據(jù)與操作數(shù)據(jù)的源代碼進行有機的結(jié)
合,形成“類”垃它,其中數(shù)據(jù)和函數(shù)都是類的成員。
封裝:行為和屬性的結(jié)合
含義:提供將所抽象出的問題的屬性(數(shù)據(jù)成員)和行為
(代碼成員)相組合的一種機制烹看,它能將這二類成員再組
合在一起国拇,形成對象或?qū)嶓w。
目的:增強使用的安全性惯殊,使用者不必了解具體的實現(xiàn)細
節(jié)酱吝,而只需要通過設(shè)計者提供的外部接口來操作它。
優(yōu)點:實現(xiàn)高度模塊化土思,從而產(chǎn)生出軟件構(gòu)件(控件)务热;
利用控件快速地組裝程序忆嗜。
客戶可以調(diào)用一個并不了解內(nèi)部機制的對象的方法
任何關(guān)于內(nèi)部的改動對客戶來說都是隱藏的
封裝圖解
27/57
封裝定義程序如何引用對象的數(shù)據(jù),封裝實際上使用方法將類的數(shù)據(jù)隱藏起來崎岂,控制用戶
對類的修改和訪問數(shù)據(jù)的程度捆毫。
繼承
28/57
繼承的概念
繼承是由已有的類創(chuàng)建新類的機制。
由繼承得到的類稱為子類(派生類)冲甘,被繼承的類稱為父類
(超類)(基類)
繼承的原則
子類繼承父類的成員變量和成員方法
子類不繼承父類的構(gòu)造方法绩卤,能夠繼承父類的析構(gòu)方法
子類不能刪除父類的成員,但可以重定義父類成員
子類可以增加自己的成員
繼承的作用
實現(xiàn)軟件可重用的重要方式
增強軟件可擴充性
提高軟件的可維護性
面向?qū)ο笾械膬蓚€重要概念:抽象和分類江醇。
29/57
抽象和分類是人們認識世界的基本方法:
抽象是將現(xiàn)實世界中客觀存在的事務(wù)映射到意識中的一種
方法濒憋。
分類是指確定這些抽象到意識中的概念之間的關(guān)系。
這些關(guān)系的基本形式包括一般到特殊和整體與局部陶夜。
在面向?qū)ο笾辛萃裕话愕教厥獾年P(guān)系用繼承(Inheritance)表
示;整體與局部的關(guān)系用組合(composition)表示条辟。
30/57
Pyhton中支持多繼承
31/57
# 定義一個父類
class A:
def printA(self):
print('----A----')
# 定義一個父類
class B:
def printB(self):
print('----B----')
# 定義一個子類黔夭,繼承自A、B
class C(A,B):
def printC(self):
print('----C----')
obj_C = C()
obj_C.printA()
obj_C.printB()
#運行結(jié)果:----A--------B----
Super()用法
super()用來引用當(dāng)前對象的父類捂贿,用super()可以實現(xiàn)對
父類成員的訪問纠修。
訪問父類被隱藏的成員變量,如:
super().variable
調(diào)用父類中被覆蓋的方法厂僧,如:
super().Method([paramlist])
調(diào)用父類的構(gòu)造函數(shù)扣草,如:
super.__init__([paramlist])
注意:super()維系了整個繼承關(guān)系
32/57
多態(tài)
什么是多態(tài)?
一個對象在不同的情況下颜屠,具有不同的形態(tài)辰妙,用于強類型
語言。是使用在繼承和接口中實現(xiàn)甫窟。
Python中有兩種說法:
1密浑、python支持多態(tài),python是一個弱類型粗井,本身一個變 量名尔破,可以存儲任何類型的值,可以理解為多種形態(tài)
2浇衬、python不支持多態(tài)懒构,多態(tài)本身是用于強類型語言的,
python是一個弱類型耘擂,所以不支持多態(tài)
多態(tài):定義時的類型和運行時的類型不一樣胆剧,此時就成為
多態(tài)
Python “鴨子類型”
:
在程序設(shè)計中,鴨子類型(英語:duck typing)是動態(tài)類
型的一種風(fēng)格醉冤。
在這種風(fēng)格中秩霍,一個對象有效的語義篙悯,不是由繼承自特定
的類或?qū)崿F(xiàn)特定的接口,而是由當(dāng)前方法和屬性的集合決
定铃绒。
這個概念的名字來源于由James Whitcomb Riley提出的鴨
子測試鸽照,“鴨子測試”可以這樣表述:“當(dāng)看到一只鳥走起來
像鴨子、游泳起來像鴨子匿垄、叫起來也像鴨子移宅,那么這只鳥
就可以被稱為鴨子〈涣疲”
在鴨子類型中漏峰,關(guān)注的不是對象的類型本身,而是它是如
33/57
何使用的届榄。
例如浅乔,在不使用鴨子類型的語言中,我們可以編寫一個函
數(shù)铝条,它接受一個類型為鴨的對象靖苇,并調(diào)用它的走和叫方
法。
在使用鴨子類型的語言中班缰,這樣的一個函數(shù)可以接受一個
任意類型的對象贤壁,并調(diào)用它的走和叫方法。
如果這些需要被調(diào)用的方法不存在埠忘,那么將引發(fā)一個運行
時錯誤脾拆。
任何擁有這樣的正確的走和叫方法的對象都可被函數(shù)接受
的這種行為引出了以上表述,這種決定類型的方式因此得
名莹妒。
鴨子類型通常得益于不測試方法和函數(shù)中參數(shù)的類型名船,而
是依賴文檔、清晰的代碼和測試來確保正確使用旨怠。
從靜態(tài)類型語言轉(zhuǎn)向動態(tài)類型語言的用戶通常試圖添加一
些靜態(tài)的(在運行之前的)類型檢查渠驼,從而影響了鴨子類
型的益處和可伸縮性,并約束了語言的動態(tài)特性
python是一種弱類型語言鉴腻,沒有類型限制迷扇。變量的類型永 遠是通過右側(cè)的值判斷的。方法中的參數(shù)爽哎,傳遞任何值都
行谋梭。但是要考慮方法內(nèi)部的業(yè)務(wù)邏輯。
多態(tài):
1倦青、父類作為參數(shù),可以傳遞父類和子類對象
2盹舞、接口作為參數(shù)产镐,只能傳遞實現(xiàn)對象
34/57
所以有兩種理解:
1隘庄、python不支持多態(tài):python是弱類型,沒有類型限 定癣亚,無法區(qū)分父和子丑掺,或者說接口和實現(xiàn)類
2、python處處是多態(tài):python是弱類型述雾,沒有類型限 定街州,傳遞任何內(nèi)容都行
多態(tài)的作用:
提高程序的擴展性
示例:
某槍戰(zhàn)游戲中:
角色類:Role
屬性:
血量
槍支庫:考慮用什么類型存儲
當(dāng)前選擇的槍支
方法:
更換槍支
開火
槍支類:
屬性:
range射程
hurt傷害值
方法:
開火:Fire
手槍 類 PistolGun
來福槍類:RifleGun
35/57
激光槍:LaserGun
36/57
class Gun:
def __init__(self,name,range,hurt):
self.name=name
self.range = range
self.hurt = hurt
def __str__(self):
return "我是:"+self.name
def Fire(self):
print("槍-開火")
#手槍
class PistolGun(Gun):
def __init__(self, name,range,hurt):
super().__init__(name,range,hurt)
def __str__(self):
return super().__str__()
def Fire(self):
print("手槍開火。比u比u比u")
#來復(fù)槍
class RifleGun(Gun):
def __init__(self, name,range,hurt):
super().__init__(name,range,hurt)
def __str__(self):
return super().__str__()
def Fire(self):
print("來福槍開火玻孟。duang duang duang")
#激光槍
class LaserGun(Gun):
def __init__(self, name, range, hurt):
super().__init__(name, range, hurt)
def __str__(self):
return super().__str__()
37/57
def Fire(self):
print("激光槍-漬 漬 漬")
#角色
class Player:
def __init__(self,name,hp):
self.name=name
self.hp=hp
def __str__(self) -> str:
return "我是:"+self.name
class Role(Player):
def __init__(self, name, hp,guns):
super().__init__(name, hp)
self.guns=guns
self.currentGun=guns[0]
def __str__(self) -> str:
return super().__str__()
def Fire(self,g):
g.Fire()
def ChangeGun(self,num):
if num==0:
self.currentGun = self.guns[0]
elif num==1:
self.currentGun = self.guns[1]
else:
self.currentGun = self.guns[2]
p=PistolGun("手槍",100,100)
r=RifleGun("來復(fù)槍",100,1000)
l=LaserGun("激光槍",1000,1000)
38/57
guns=[p,r,l]
r=Role("police",100,guns)
r.ChangeGun(0)
print(r.currentGun)
r.Fire(r.currentGun)
實例屬性唆缴,類屬性/方法,靜態(tài)方法
類屬性
直接在類中定義的黍翎,與方法平齊面徽,不在方法里的屬性就是
類屬性
實例屬性
在方法里通過self.屬性 都是實例屬性
在了解了類基本的東西之后,下面看一下python中這幾個
概念的區(qū)別先來談一下類屬性和實例屬性
在前面的例子中我們接觸到的就是實例屬性(對象屬性)
類屬性就是類對象所擁有的屬性匣掸,它被所有類對象的實例
對象所共有趟紊,在內(nèi)存中只存在一個副本,這個和C++中類
的靜態(tài)成員變量有點類似碰酝。
對于公有的類屬性霎匈,在類外可以通過類對象和實例對象訪
問
類方法
是類對象所擁有的方法,需要用修飾器@classmethod
39/57
(注解送爸、元數(shù)據(jù))來標(biāo)識其為類方法铛嘱,對于類方法,第一
個參數(shù)必須是類對象碱璃,一般以cls作為第一個參數(shù)(當(dāng)然可
以用其他名稱的變量作為其第一個參數(shù)弄痹,但是大部分人都
習(xí)慣以'cls'作為第一個參數(shù)的名字,就最好用'cls'了)嵌器,能 夠通過實例對象和類對象去訪問肛真。
靜態(tài)方法
需要通過修飾器@staticmethod來進行修飾,靜態(tài)方法不 需要多定義參數(shù)
從類方法和實例方法以及靜態(tài)方法的定義形式就可以看出
來爽航,
類方法的第一個參數(shù)是類對象cls蚓让,那么通過cls引用的必定
是類對象的屬性和方法;
而實例方法的第一個參數(shù)是實例對象self讥珍,那么通過self引
用的可能是類屬性历极、也有可能是實例屬性(這個需要具體
分析),不過在存在相同名稱的類屬性和實例屬性的情況
下衷佃,實例屬性優(yōu)先級更高趟卸。
靜態(tài)方法中不需要額外定義參數(shù),因此在靜態(tài)方法中引用
類屬性的話,必須通過類對象來引用
總結(jié)
方法是代碼重用的重要手段
40/57
控制好代碼被訪問的程度 可以加強代碼的安全性
封裝锄列、繼承和多態(tài)是面向?qū)ο蟮幕咎卣?/p>
封裝特性通過訪問權(quán)限的設(shè)定將類的實現(xiàn)細節(jié)隱藏图云,提供
接口供外部訪問
繼承和組合是類間的基本關(guān)系,是軟件復(fù)用的重要方法
多態(tài)是面向?qū)ο蟮闹匾獦?biāo)志
本章作業(yè)
1:創(chuàng)建一個圓Circle類邻邮,為該類提供兩個方法竣况,方法一用 于求圓的面積,方法二用于求圓的周長筒严,同時為該類提供
一個變量r表示半徑丹泉,一個變量PI表示圓周率。為該類提供
一個魔法方法鸭蛙,用于初始化屬性的值
2:(1)創(chuàng)建Rectangle類摹恨,添加屬性width、height规惰;
(2)在Rectangle類中添加兩種方法計算矩形的周長和面
積睬塌;(3)編程利用Rectangle輸出一個矩形的周長和面積
3:飼養(yǎng)員類,動物類歇万,食物類揩晴。實現(xiàn)飼養(yǎng)員給動物喂食
物。
4:創(chuàng)建一個賬戶Account類贪磺,該類有id:賬戶號
碼,password:賬戶密碼,name:真實姓名,personId:身份證
號碼 字符串類型,email:客戶的電子郵箱,balance:賬戶余
額.方法:deposit: 存款方法,參數(shù)是數(shù)字型的金
額;withdraw:取款方法,參數(shù)是數(shù)字型的金額.魔法方法:魔
法方法用于設(shè)置屬性
5:某班有若干學(xué)生(學(xué)生對象放在一個List中)硫兰,每個學(xué)生有 一個姓名屬性、學(xué)號和考試成績屬性寒锚,某次考試結(jié)束后劫映,
41/57
每個學(xué)生都獲得了一個考試成績。請求出本班的最高分,最
低分,總分以及平均分.
6:設(shè)計一個繼承關(guān)系其中存在動物類Animal刹前、狗類Dog和
貓類Cat,對于貓類和狗類都有一個吃eat方法泳赋,但是貓和狗
的吃eat方法的實現(xiàn)不同,請合理的設(shè)計出Animal Dog Cat
這3個類關(guān)系
7:設(shè)計一個形狀類Shape,方法:求周長和求面積形狀類的
子類:Rect(矩形),Circle(圓形) Rect類的子類:Square(正方
形)不同的子類會有不同的計算周長和面積的方法創(chuàng)建三個
不同的形狀對象,放在列表里,分別打印出每個對象的周長
和面積
8:寫出一個類People喇喉,并由該類做基類派生出子類
Employee和Teacher祖今。其中People類具有name、age兩個
保護成員變量拣技,分別為String類型千诬、整型,且具有公有的
GetAge成員函數(shù)膏斤,用于返回age變量的值徐绑。Employee類具
有保護成員變量empno,Teacher類有teacherNo成員變
量。
9:(1)設(shè)計一個User類莫辨,其中包括用戶名傲茄、口令等屬性 以及構(gòu)造方法毅访。獲取和設(shè)置口令的方法,顯示和修改用戶
名的方法等烫幕。編寫應(yīng)用程序測試User類俺抽。
(2)定義一個student類,其中包括用戶名、姓名较曼、性別、
出生年月等屬性以及Init()——初始化各屬性振愿、Display()
——顯示各屬性捷犹、Modify()——修改姓名等方法。實現(xiàn)并
測試這個類冕末。
(3)從上題的student類中派生出Granduate(研究生)
類萍歉,添加屬性:專業(yè)subject、導(dǎo)師adviser档桃。重載相應(yīng)的
42/57
成員方法枪孩。并測試這個類。
10.【基本題】定義一個Person類藻肄,它包含數(shù)據(jù)成員age,
name和gender蔑舞。從Person中派生一個類Employee,在新類
中添加一個數(shù)據(jù)成員,存儲個人的number.再從Employee
中派生一個類Executive,每個派生類都應(yīng)該定義一個函
數(shù)嘹屯,來顯示相關(guān)的信息(名稱和類型攻询,如”Fred Smith is
an Employee”)。編寫一個Main()函數(shù)州弟,生成兩個數(shù)組钧栖,
一個數(shù)組包含5個Executive對象,另一個數(shù)組包含5個一般
的Employee對象婆翔,然后顯示它們的信息拯杠。另外,調(diào)用從
Employee類繼承的成員函數(shù)啃奴,顯示Executive信息潭陪。
11.【基本題】設(shè)計一個圖書管理系統(tǒng),基類為類Book,要求
有書名和作者屬性, 由Book類派生子類AudioBook(有聲
書纺腊,需要具有演說者屬性)畔咧,對于Book和AudioBook進行合
理的屬性及行為的抽象,同時實現(xiàn)該類的控制臺打印函數(shù)
12.某公司雇員(Employee)包括經(jīng)理(Manager)揖膜,技
術(shù)人員(Technician)和銷售員(Salesman)誓沸。以
Employee類為基類派生出Manager,Technician和
Salesman類壹粟;Employee類的屬性包括姓名拜隧、職工號宿百、工
資級別,月薪(實發(fā)基本工資加業(yè)績工資)洪添。操作包括月
薪計算函數(shù)(Pay())垦页,該函數(shù)要求輸入請假天數(shù),扣去應(yīng) 扣工資后干奢,得出實發(fā)基本工資痊焊。
Technician類派生的屬性有每小時附加酬金和當(dāng)月工作時
數(shù),及研究完成進度系數(shù)忿峻。業(yè)績工資為三者之積薄啥。也包括
同名的Pay()函數(shù),工資總額為基本工資加業(yè)績工資逛尚。
Salesman類派生的屬性有當(dāng)月銷售額和酬金提取百分比垄惧,
業(yè)績工資為兩者之積。也包括同名的Pay()函數(shù)绰寞,工資總額
為基本工資加業(yè)績工資到逊。
43/57
Manager類派生屬性有固定獎金額和業(yè)績系數(shù),業(yè)績工資 為兩者之積滤钱。工資總額也為基本工資加業(yè)績工資觉壶。編程實
現(xiàn)工資管理。
可選題
項目名稱:Bank Account Management System 銀行賬戶
管理系統(tǒng) 簡稱BAM
練習(xí)1:(面向?qū)ο蠡A(chǔ)語法)
寫一個賬戶類(Account),
屬性: id:賬戶號碼 長整數(shù)
password:賬戶密碼
name:真實姓名
personId:身份證號碼 字符串類型
email:客戶的電子郵箱
balance:賬戶余額
方法: deposit: 存款方法,參數(shù)是float型的金額
withdraw:取款方法,參數(shù)是float型的金額
構(gòu)造方法:
有參和無參,有參構(gòu)造方法用于設(shè)置必要的屬性
練習(xí)2:(封裝)
將Account類作成完全封裝,注意:要辨別每個屬性的是否需
要公開
練習(xí)3:(繼承,多態(tài))
44/57
銀行的客戶分為兩類,儲蓄賬戶(SavingAccount)和信用賬
戶(CreditAccount),區(qū)別在于儲蓄賬戶不允許透支,而信用
賬戶可以透支,并允許用戶設(shè)置自己的透支額度.
注意:CreditAccount需要多一個屬性 ceiling 透支額度
為這兩種用戶編寫相關(guān)的類
同時要求編寫B(tài)ank類,屬性:
1.當(dāng)前所有的賬戶對象的集合,存放在數(shù)組中
2.當(dāng)前賬戶數(shù)量
方法:
1.用戶開戶,需要的參數(shù):id,密碼,密碼確認,姓名,身份證號
碼,郵箱,賬戶類型(int),返回新創(chuàng)建的Account對象
2.用戶登錄,參數(shù):id,密碼 返回Account對象,提示 用
s1.equals(s2)判斷s1和s2兩個字符串內(nèi)容是否相等
3.用戶存款,參數(shù):id,存款數(shù)額,返回修改過的Account對象
4.用戶取款,參數(shù):id,取款數(shù)額,返回修改過的Account對象
5.設(shè)置透支額度 參數(shù):id,新的額度 ,返回修改過的Account
對象.這個方法需要驗證賬戶是否是信用賬戶
用戶會通過調(diào)用Bank對象以上的方法來操作自己的賬戶, 請分析各個方法需要的參數(shù)
另外,請為Bank類添加幾個統(tǒng)計方法
1.統(tǒng)計銀行所有賬戶余額總數(shù)
2.統(tǒng)計所有信用賬戶透支額度總數(shù)
寫個主方法測試你寫的類
11異常
異常簡介
什么是異常?
45/57
異常實際上是程序中錯誤導(dǎo)致中斷了正常的指令流的一種
事件.
當(dāng)Python檢測到一個錯誤時菩暗,解釋器就無法繼續(xù)執(zhí)行了掰曾,
反而出現(xiàn)了一些錯誤的提示,這就是所謂的"異常"
傳統(tǒng)處理異常方法?
if...else...
正確異常處理
try:
語句
except :
語句
else:
語句
處理異常的優(yōu)點:
綜合上面的說法和傳統(tǒng)的方法比較異常的優(yōu)點:
1.把錯誤代碼從常規(guī)代碼中分離出來
2.把錯誤傳播給調(diào)用堆棧
3. 按錯誤類型和錯誤差別分組
4. 系統(tǒng)提供了對于一些無法預(yù)測的錯誤的捕獲和處理
5. 克服了傳統(tǒng)方法的錯誤信息有限的問題
什么情況下使用例外機制停团?
1.當(dāng)方法因為自身無法控制的原因而不能完成其任務(wù)
文件不存在旷坦,網(wǎng)絡(luò)連接無法建立……
2.處理在方法、類庫佑稠、類中拋出的例外
如FileInputStream.read產(chǎn)生IOException
46/57
3.在大的項目中采用統(tǒng)一的方式處理例外時
如編寫一個文字處理器
4.例外應(yīng)該是不經(jīng)常發(fā)生但卻可能發(fā)生的故障
一定發(fā)生的事件不應(yīng)該用例外機制來處理
5.例外處理用于使系統(tǒng)從故障中恢復(fù)
提示信息/不產(chǎn)生無效的結(jié)果/釋放資源
注意事項:
1.不同的例外處理策略
關(guān)鍵性應(yīng)用(處理所有例外)
實驗軟件(可以忽略許多例外)
2.終止程序會導(dǎo)致資源泄漏秒梅,利用例外處理釋放資源
3.盡可能近地處理例外,這樣程序清晰易讀
4.能在局部處理的錯誤不要使用例外機制
例外機制的處理比正常處理效率低
BaseException 所有異常的基類
SystemExit 解釋器請求退出
KeyboardInterrupt 用戶中斷執(zhí)行(通常是輸入^C)
Exception 常規(guī)錯誤的基類
StopIteration 迭代器沒有更多的值
GeneratorExit 生成器(generator)發(fā)生異常來通知退出
StandardError 所有的內(nèi)建標(biāo)準(zhǔn)異常的基類
ArithmeticError 所有數(shù)值計算錯誤的基類
FloatingPointError 浮點計算錯誤
OverflowError 數(shù)值運算超出最大限制
ZeroDivisionError 除(或取模)零 (所有數(shù)據(jù)類型)
AssertionError 斷言語句失敗
AttributeError 對象沒有這個屬性
47/57
EOFError 沒有內(nèi)建輸入,到達EOF 標(biāo)記
EnvironmentError 操作系統(tǒng)錯誤的基類
IOError 輸入/輸出操作失敗
OSError 操作系統(tǒng)錯誤
WindowsError 系統(tǒng)調(diào)用失敗
ImportError 導(dǎo)入模塊/對象失敗
LookupError 無效數(shù)據(jù)查詢的基類
IndexError 序列中沒有此索引(index)
KeyError 映射中沒有這個鍵
MemoryError 內(nèi)存溢出錯誤(對于Python 解釋器不是致
命的)
NameError 未聲明/初始化對象 (沒有屬性)
UnboundLocalError 訪問未初始化的本地變量
ReferenceError 弱引用(Weak reference)試圖訪問已經(jīng)垃
圾回收了的對象
RuntimeError 一般的運行時錯誤
NotImplementedError 尚未實現(xiàn)的方法
SyntaxError Python 語法錯誤
IndentationError 縮進錯誤
TabError Tab 和空格混用
SystemError 一般的解釋器系統(tǒng)錯誤
TypeError 對類型無效的操作
ValueError 傳入無效的參數(shù)
UnicodeError Unicode 相關(guān)的錯誤
UnicodeDecodeError Unicode 解碼時的錯誤
UnicodeEncodeError Unicode 編碼時錯誤
UnicodeTranslateError Unicode 轉(zhuǎn)換時錯誤
Warning 警告的基類
DeprecationWarning 關(guān)于被棄用的特征的警告
48/57
FutureWarning 關(guān)于構(gòu)造將來語義會有改變的警告
OverflowWarning 舊的關(guān)于自動提升為長整型(long)的
警告
PendingDeprecationWarning 關(guān)于特性將會被廢棄的警告
RuntimeWarning 可疑的運行時行為(runtime behavior) 的警告
SyntaxWarning 可疑的語法的警告
UserWarning 用戶代碼生成的警告
異常處理方式
捕獲異常 try...except...
看如下示例:
try:
print('-----test--1---')
open('123.txt','r')
print('-----test--2---')
except IOError as resault:
print(resault)
說明:此程序看不到任何錯誤舌胶,因為用except 捕獲到了IOError異常捆蜀,并添加了處理的方法
pass 表示實現(xiàn)了相應(yīng)的實現(xiàn),但什么也不做幔嫂;
print語句见咒,會輸出異常信息
49/57
咱們應(yīng)該對else并不陌生钦铁,在if中侣灶,它的作用是當(dāng)條件不滿
足時執(zhí)行的實行倔既;同樣在try...except...中也是如此,即如
果沒有捕獲到異常切心,那么就執(zhí)行else中的事情
try:
#num = 100
print(num)
except NameError as errorMsg:
print('產(chǎn)生錯誤了:%s'%errorMsg)
else:
print('沒有捕獲到異常飒筑,真高興')print('over...')
try...finally...語句用來表達這樣的情況:
在程序中片吊,如果一個段代碼必須要執(zhí)行,即無論異常是否
產(chǎn)生都要執(zhí)行协屡,那么此時就需要使用finally俏脊。 比如文件關(guān)
閉,釋放鎖肤晓,把數(shù)據(jù)庫連接返還給連接池等
50/57
import time
try:
f = open('abc.txt')
try:
while True:
content = f.readline()
if len(content) == 0:
break
time.sleep(2)
print(content)
except:
#如果在讀取文件的過程中爷贫,
#產(chǎn)生了異常,那么就會捕獲到
#比如 按下了 ctrl+c
pass
finally:
f.close()
print('關(guān)閉文件')
except:
print("沒有這個文件")
finally:
1.捕獲例外的最后一步是通過finally語句為例外處理提
供一個統(tǒng)一的出口材原,使得在控制流程轉(zhuǎn)到程序的其他部分
以前沸久,能夠?qū)Τ绦虻臓顟B(tài)作統(tǒng)一的管理。
2.無論try所指定的程序塊中是否拋出例外余蟹,也無論
except語句的例外類型是否與所拋棄的例外的類型一致,
finally所指定的代碼都要被執(zhí)行子刮,它提供了統(tǒng)一的出口威酒。
3.通常在finally語句中可以進行資源的清除工作,如關(guān) 閉打開的文件挺峡、刪除臨時文件等葵孤。
finally和return的關(guān)系:
1.當(dāng)try和except中有return時,finally仍然會執(zhí)行橱赠;
2.finally是在return后面的表達式運算后執(zhí)行的(此時并沒
51/57
有返回運算后的值尤仍,而是先把要返回的值保存起來,不管
finally中的代碼如何修改狭姨,返回的值都不會改變宰啦,仍然是
之前保存的值),所以函數(shù)返回值是在finally執(zhí)行前確定
的饼拍;
3.finally中不可以有return赡模,否則語法錯誤
練習(xí)捕捉異常
編寫程序,包含四種異常
算術(shù)異常, 字符串越界,數(shù)組越界,格式異常(字符串轉(zhuǎn)數(shù)字)
觀察輸出信息:
每個異常對象可以直接給出信息
拋出異常
raise ExceptionObj;
拋出異常: 不是出錯產(chǎn)生,而是人為地拋出
1.任何從Exception派生的類都可以用raise語句拋出,拋出 例外用來表明程序遇到的錯誤無法正常執(zhí)行而需要例外處
理
2.例外拋出點后的代碼在拋出例外后不再執(zhí)行
也可以說例外的拋出終止了代碼段的執(zhí)行
自定義異常
異常是一個類,用戶定義的異常必須繼承自Exception
52/57
'''自定義的異常類'''
class ShortInputException(Exception):
def __init__(self, length, atleast):
super().__init__()
self.length = length
self.atleast = atleast
def main()
try:
s = input('請輸入 --> ')
if len(s) < 3:
#raise引發(fā)一個你定義的異常
raise ShortInputException(len(s), 3)
#x這個變量被綁定到了錯誤的實例
except ShortInputException as result:
print(result)
print('ShortInputException: 輸入的長度是 %d,長度至少應(yīng)是 %d'% (result.length,
result.atleast))
else:
print('沒有異常發(fā)生.')
main()
總結(jié)
異常簡介
異常處理方式
捕捉異常
拋出自定義異常
自定義異常
本章作業(yè)
作業(yè)一
自定義一個學(xué)生類师抄,屬性有 姓名 年齡漓柑,如果用戶在給學(xué)
生年齡賦值時,年齡小于0拋出一個AgeLT0Exception叨吮,大
53/57
于150 拋出一個AgeGT150Exception
作業(yè)二
在定義銀行類時,若取錢數(shù)大于余額則作為異常處理
(InsufficientFundsException).
思路:產(chǎn)生異常的條件是余額少于取額, 因此是否拋出異常
要判斷條件
取錢是Withdrawal方法中定義的動作,因此在該方法中產(chǎn)生
異常.
處理異常安排在調(diào)用Withdrawal的時候,因此Withdrawal
方法要聲明異常,由上級方法調(diào)用
要定義好自己的異常類
要求:捕捉到的異常對象內(nèi)有余額和取額的信息
12自定義模塊
自定義模塊
Python許多時候自己定義的函數(shù)辆布,需要經(jīng)常調(diào)用時; 就可以自己定義一個模塊茶鉴,將常用函數(shù)寫入模塊里锋玲,下次
使用常用函數(shù)時直接導(dǎo)入模塊,就可以使用函數(shù)了蛤铜;
以下函數(shù)說明嫩絮,函數(shù)功能:解決以.py腳本運行時和以.exe
運行時讀取文件路徑兼容性問題丛肢。
測試模塊
python在執(zhí)行一個文件時有個變量__name__可以根據(jù)
__name__變量的結(jié)果能夠判斷出,是直接執(zhí)行的python 腳本還是被引入執(zhí)行的剿干,從而能夠有選擇性的執(zhí)行測試代
碼__name__如果寫在被直接運行的主文件中蜂怎,
54/57
是”__main__”如果寫在被導(dǎo)入的文件中,運行主文件的時
候置尔,導(dǎo)入文件中的__name__是”模塊的名字”
__name__這個系統(tǒng)變量顯示了當(dāng)前模塊執(zhí)行過程中的名
稱杠步,如果當(dāng)前程序運行在這個模塊中,__name__ 的名稱
就是__main__如果不是榜轿,則為這個模塊的名稱幽歼。
__main__一般作為函數(shù)的入口,類似于C語言谬盐,尤其在大 型工程中甸私,常常有
if __name__ == "__main__"
:來表明整個工程開始運行的入口。
__all__設(shè)置
python模塊中的__all__屬性飞傀,
可用于模塊導(dǎo)入時限制皇型,如:
from module import *
此時被導(dǎo)入模塊若定義了__all__屬性,則只有__all__內(nèi)
指定的屬性砸烦、方法弃鸦、類可被導(dǎo)入。
若沒定義幢痘,則導(dǎo)入模塊內(nèi)的所有公有屬性唬格,方法和類 。
__all__展現(xiàn)了模塊的內(nèi)容大綱颜说,而且也更清晰的提供了外 部訪問接口购岗。
如果一個文件中有__all__變量,那么也就意味著這個變量
中的元素脑沿,不會被from xxx import *時導(dǎo)入
包
55/57
包
通常包總是一個目錄藕畔,可以使用import導(dǎo)入包,或者from
+ import來導(dǎo)入包中的部分模塊庄拇。
包目錄下為首的一個文件便是 __init__.py注服。然后是一些模
塊文件和子目錄,假如子目錄中也有 __init__.py 那么它
就是這個包的子包了措近。
在創(chuàng)建許許多多模塊后溶弟,我們可能希望將某些功能相近的
文件組織在同一文件夾下,這里就需要運用包的概念了瞭郑。
包對應(yīng)于文件夾辜御,使用包的方式跟模塊也類似,唯一需要
注意的是屈张,當(dāng)文件夾當(dāng)作包使用時擒权,文件夾需要包含
__init__.py文件袱巨,主要是為了避免將文件夾名當(dāng)作普通的
字符串。__init__.py的內(nèi)容可以為空碳抄,一般用來進行包的
某些初始化工作或者設(shè)置__all__值愉老,__all__是在from
package-name import *這語句使用的,全部導(dǎo)出定義過
的模塊剖效。
可以從包中導(dǎo)入單獨的模塊嫉入。
1). import PackageA.SubPackageA.ModuleA,使用時必須
用全路徑名
2). 變種: from PackageA.SubPackageA import ModuleA, 可以直接使用模塊名而不用加上包前綴。
3). 也可以直接導(dǎo)入模塊中的函數(shù)或變量:from
PackageA.SubPackageA.ModuleA import functionA
import語句語法:
1. 當(dāng)使用from package import item時璧尸,item可以是
package的子模塊或子包咒林,或是其他的定義在包中的名字
(比如一個函數(shù)、類或變量) 首先檢查item是否定義在
56/57
包中爷光,不過沒找到垫竞,就認為item是一個模塊并嘗試加載
它,失敗時會拋出一個ImportError異常蛀序。
2. 當(dāng)使用import item.subitem.subsubitem語法時件甥,最后
一個item之前的item必須是包,最后一個item可以是一個
模塊或包哼拔,但不能是類、函數(shù)和變量
3. from pacakge import * 如果包的__init__.py定義了一
個名為__all__的列表變量瓣颅,它包含的模塊名字的列表將作
為被導(dǎo)入的模塊列表倦逐。 如果沒有定義__all__, 這條語
句不會導(dǎo)入所有的package的子模塊宫补,它只保證包
package被導(dǎo)入檬姥,然后導(dǎo)入定義在包中的所有名字。
python包是:
包是一個有層次的文件目錄結(jié)構(gòu)粉怕,它定義了由n個模塊或n
個子包組成的python應(yīng)用程序執(zhí)行環(huán)境健民。
通俗一點:包是一個包含__init__.py 文件的目錄,該目錄
下一定得有這個__init__.py文件和其它模塊或子包贫贝。
包將有聯(lián)系的模塊組織在一起秉犹,即放到同一個文件夾下,
并且在這個文件夾創(chuàng)建一個名字為__init__.py 文件稚晚,那么 這個文件夾就稱之為包有效避免模塊名稱沖突問題崇堵,讓應(yīng)
用組織結(jié)構(gòu)更加清晰
__init__.py 控制著包的導(dǎo)入行為
__init__.py為空僅僅是把這個包導(dǎo)入,不會導(dǎo)入包中的模
塊
__all__在__init__.py文件中客燕,定義一個__all__變量鸳劳,它
控制著 from 包名 import *時導(dǎo)入的模塊
總結(jié)
57/57
自定義模塊
自定義包及__init__.py的意義