Python高級基礎
1.文件
1.1文件操作步驟
-
打開文件
-
讀寫等操作
-
關閉文件
1.1.1文件操作的函數/方法
序號 | 函數/方法 | 說明 |
---|---|---|
01 | open | 打開文件,並且返回文件操作對象 |
02 | read | 將文件內容讀取到內存 |
03 | write | 將指定內容寫入文件 |
04 | close | 關閉文件 |
-
open
函數負責打開文件,並且返回文件對象 -
read
/write
/close
三個方法都需要通過 文件對象 來調用 -
open
函數的第一個參數是要打開的文件名(文件名區分大小寫)-
如果文件 存在,返回 文件操作對象
-
如果文件 不存在,會 拋出異常
-
-
read
方法可以一次性 讀入 並 返回 文件的 所有內容 -
close
方法負責 關閉文件
1)打開/寫入文件
在Python中,使用open函數,可以打開一個已經存在的文件,或者創建一個新文件,語法如下:
open(name, mode)
name:是要打開目標文件名的字符串(可以包含文件所在的具體路徑)
mode:設置打開文件的模式(訪問模式):只讀、寫入、追加等
訪問方式 | 說明 |
---|---|
r | 以只讀方式打開文件。文件的指針將會放在文件的開頭,這是默認模式。如果文件不存在,拋出異常 |
w | 以只寫方式打開文件。如果文件存在會被覆蓋。如果文件不存在,創建新文件 |
a | 以追加方式打開文件。如果該文件已存在,文件指針將會放在文件的結尾。如果文件不存在,創建新文件進行寫入 |
r+ | 以讀寫方式打開文件。文件的指針將會放在文件的開頭。如果文件不存在,拋出異常 |
w+ | 以讀寫方式打開文件。如果文件存在會被覆蓋。如果文件不存在,創建新文件 |
a+ | 以讀寫方式打開文件。如果該文件已存在,文件指針將會放在文件的結尾。如果文件不存在,創建新文件進行寫入 |
提示
-
頻繁的移動文件指針,會影響文件的讀寫效率,開發中更多的時候會以 只讀、只寫 的方式來操作文件
打開文件並進行寫入示例
# 打開文件 f = open("README", "w") f.write("hello python!\n") f.write("今天天氣真好") # 關閉文件 f.close()
2)讀取文件
1. read()
文件對象.read(num)
num表示要從文件中讀取的數據的長度(單位都是字節),如果沒有傳入num,那麼就表示讀取文件的所有數據
一次性讀取文件內容
# 1. 打開 - 文件名需要注意大小寫 file = open("README") # 2. 讀取 text = file.read() print(text) # 3. 關閉 file.close()
注意:read
方法執行後,會把 文件指針 移動到 文件的末尾
文件指針
文件指針 標記 從哪個位置開始讀取數據
第一次打開 文件時,通常 文件指針會指向文件的開始位置
當執行了
read
方法後,文件指針 會移動到 讀取內容的末尾
默認情況下會移動到 文件末尾
2. readlines()
readlines可以按照行的方式把整個文件中的內容按行進行一次性讀取,並且返回的是一個列表,其中每一行的數據爲一個元素
fp = open("E:\student.txt", "r") result = fp.readlines() print(result) # ['aaa\n', 'bbb\n', 'ccc\n', 'ddd'] fp.close()
3. readline()
-
readline
方法可以一次讀取一行內容 -
方法執行後,會把 文件指針 移動到下一行,準備再次讀取,適用於讀取大文件
讀取大文件的正確姿勢
# 打開文件 file = open("README") while True: # 讀取一行內容 text = file.readline() # 判斷是否讀到內容 if not text: break # 每讀取一行的末尾已經有了一個 `\n` print(text, end="") # 關閉文件 file.close()
1.1.2 r+ 和 w+ 和 a+ 區別
""" 1. r+ 和 w+ a+區別 2. 文件指針對數據讀取的影響 3. test.txt已存在並且有數據,test1.txt不存在 """ # r+: 文件不存在則報錯,文件指針在開頭,能夠讀出數據 # f = open('test1.txt', 'r+') # f = open('test.txt', 'r+') # w+:文件不存在會新建文件,文件指針在開頭,讀數據時會用新內容覆蓋原內容 # f = open('test1.txt', 'w+') # f = open('test.txt', 'w+') # a+:文件不存在會新建文件,文件指針在末尾,不能夠讀出數據 f = open('test1.txt', 'a+') f = open('test.txt', 'a+') con = f.read() print(con) f.close()
1.1.3 seek()
作用:用來移動文件指針
語法如下:
文件對象.seek(偏移量, 起始位置)
起始位置:
0:文件開頭
1:當前位置
2:文件結尾
# r 改變文件指針位置:改變讀取數據開始位置或把文件指針放在末尾(無法讀取數據) fp = open('E:/student.txt', 'r') # 改變文件指針,讀取改變後的數據 fp.seek(6, 0) # 文件指針放在末尾(無法讀取數據) # fp.seek(0, 2) con = fp.read() print(con) fp.close()
1.2 文件備份
需求:用戶輸入當前目錄下任意文件名,程序完成對該文件的備份功能(備份文件名爲xx[備份]後綴,例如:test[備份].txt)
1.2.1步驟
-
接收用戶輸入的文件名
-
規劃備份文件名
-
備份文件寫入數據
1.2.2代碼實現
# 1.接收用戶輸入目標文件 old_name = input('請輸入你要備份的文件名:') # 2.規劃備份文件的名字 # 2.1提取目標文件後綴 index = old_name.rfind('.') # 2.2有效文件才備份 if index > 0: postfix = old_name[index:] else: print("輸入文件名無效!") # 2.3組織新文件名:舊文件名 + [備份] + 後綴 new_name = old_name[:index] + '[備份]' + postfix print(new_name) # 3.備份文件寫入數據(數據和原文件一樣) # 3.1打開文件 old_fp = open(old_name, 'rb') new_fp = open(new_name, 'wb') # 3.2將原文件數據寫入備份文件 while True: con = old_fp.read(1024) if len(con) == 0: break new_fp.write(con) # 3.3關閉文件 old_fp.close() new_fp.close()
1.3文件和文件夾的操作
在Python中文件和文件夾的操作要藉助os模塊裏面的相關功能,具體步驟如下:
-
導入os模塊
import os
-
使用os模塊相關功能
os.函數名()
1.3.1文件重命名
os.rename(目標文件名,新文件名)
1.3.2刪除文件
os.remove(目標文件名)
# 導入模塊os import os # 1.rename():重命名 os.rename('test.txt', 'lyc.txt') # 2.remove():刪除文件 os.remove('test[備份].txt')
1.3.3創建文件夾
os.mkdir(文件夾名字)
1.3.4刪除文件夾
os.rmdir(文件夾名字)
1.3.5獲取當前目錄
os.getcwd()
1.3.6改變默認目錄
os.chdir(目錄)
1.3.7獲取目錄列表
os.listdir(目錄)
# 導入模塊os import os # 1.mkdir():創建文件夾 # os.mkdir('lyc') # 2.rmdir():刪除文件夾 # os.rmdir('lyc') # 3.getcwd():獲取當前目錄 path = os.getcwd() print(path) # 4.chdir():改變默認目錄路徑 # 需求:在lyc文件夾裏創建文件夾aa # os.mkdir('lyc') # os.chdir('lyc') # os.mkdir('aa') # 5.listdir():獲取目錄列表 print(os.listdir('lyc')) # 6.rename():重命名文件夾 os.rename('lyc', 'bb')
1.3.8應用案例
需求:批量修改文件名,既可添加指定字符串,又能刪除指定字符串
-
步驟
-
設置添加刪除字符串的標識
-
獲取指定目錄的所有文件
-
將原有文件名添加/刪除指定字符串,構造新名字
-
os.rename()
重命名
-
-
代碼
# 需求1:把code文件夾所有文件重命名 Python_xxxx import os # 設置重命名標識:如果flag取值爲1則添加指定字符,flag取值爲2則刪除指定字符 flag = 1 # 獲取指定目錄 dir_name = './' # 獲取指定目錄的文件列表 file_list = os.listdir(dir_name) # 遍歷文件列表內的文件 for name in file_list: # 添加指定字符 if flag == 1: new_name = 'Python_' + name # 刪除指定字符 elif flag == 2: num = len('Python_') new_name = name[num:] # 打印新文件名,測試程序正確性 print(new_name) # 重命名 os.rename(dir_name+name,dir_name+new_name)
2.面向對象
面向對象就是將編程當成一個是一個事物,對外界來說,事物是直接食用的,不用去管他內部的情況。而編程就是設置事物能夠做什麼事
2.1類和對象
在面向對象編程過程中,有兩個重要組成部分:類和對象
類和對象關係:用類去創建一個對象
2.1.1類
類是一系列具有相同特徵和行爲的事物的統稱,是一個抽象概念,不是真實存在的事物
-
特徵即是屬性
-
行爲即是方法
2.1.2對象
對象是創建出來的真實存在的事物
2.2面向對象實現方法
2.2.1定義類
Python2
中類分爲:經典類和新式類
-
語法
class 類名(): 代碼 .......
注意:類名要滿足標識符的命名規則,同時遵循大駝峯命名習慣
2.2.2創建對象
對象又名實例
-
語法
對象名 = 類名()
-
體驗
# 需求:洗衣機 功能:洗衣服 # 1.定義洗衣機類 class Washer(): def wash(self): print("洗衣服") # 2.創建對象 haier = Washer() # 實例方法 對象名.wash() haier.wash()
2.2.3self
self指的是調用該函數的對象
# 需求:洗衣機 功能:洗衣服 # 1.定義洗衣機類 class Washer(): def wash(self): print("我會洗衣服") # <__main__.Washer object at 0x000001EAE7699A58> print(self) # 2.創建對象 haier = Washer() # <__main__.Washer object at 0x000001EAE7699A58> print(haier) haier.wash()
2.3添加和獲取對象屬性
屬性即是特徵,比如:洗衣機的寬度、高度、重量...
對象屬性既可以是在類外面添加和獲取,也能在類裏面添加和獲取
2.3..1類外面添加對象屬性
-
語法
對象名.屬性名 = 值
-
體驗
haier.width = 500 haier.height = 800
2.3.2類外面獲取對象屬性
-
語法
對象名.屬性名
-
體驗
print(f'haier洗衣機的寬度是{haier.width}') print(f'haier洗衣機的高度是{haier.height}')
2.4類裏面獲取對象屬性
-
語法
self.屬性名
-
體驗
# 1.定義洗衣機類 class Washer(): def print_info(self): # 類裏面獲取實例屬性 print(f'haier洗衣機的寬度是{self.width}') print(f'haier洗衣機的高度是{self.height}') # 2.創建對象 haier = Washer() haier.width = 400 haier.height = 500 haier.print_info()
2.5魔法方法
在Python中,__
xx__
()的函數叫做魔法方法,指的是具有特殊功能的函數
2.5.1__init__()
2.5.1.1體驗__init__()
__init__
方法的作用:初始化對象。
class Washer(): # 定義__init__,添加實例屬性 def __init__(self): # 添加實例屬性 self.width = 500 self.height = 800 self.color = 'red' def print_info(self): # 類裏面調用實例屬性 print(f'洗衣機的寬度是{self.width},高度是{self.height}') haier = Washer() # 洗衣機的寬度是500,高度是800 haier.print_info()
注意:
__init__()
方法,在創建一個對象時默認被調用,不需要手動調用
__init__(self)
中的self參數,不需要開發者傳遞,python解釋器會自動把當前的對象引用傳遞過去
2.5.1.2帶參數的__init()
思考:一個類可以創建多個對象,如何對不同的對象設置不同的初始化屬性呢?
答:傳參數
class Washer(): # 定義__init__,添加實例屬性 def __init__(self, width, height, color): # 添加實例屬性 self.width = width self.height = height self.color = color def print_info(self): # 類裏面調用實例屬性 print(f'洗衣機的寬度是{self.width},高度是{self.height},顏色是{self.color}') haier1 = Washer(100, 300, 'red') haier1.print_info() haier2 = Washer(400, 500, 'white') haier2.print_info()
2.5.2__str__()
當使用print輸出對象的時候,默認打印對象的內存地址。如果定義了__str__
方法,那麼就會打印從這個方法中return的數據
class Washer(): # 定義__init__,添加實例屬性 def __init__(self, width, height, color): # 添加實例屬性 self.width = width self.height = height self.color = color # 解釋說明信息 def __str__(self): return '洗衣機寬度是:' + str(self.width) + ',洗衣機寬度:' + str(self.height) + ',洗衣機顏色是:' + self.color haier1 = Washer(100, 300, 'red') print(haier1)
2.5.3__del__()
當刪除對象時,python解釋器也會默認調用__del__()
方法
class Washer(): # 定義__init__,添加實例屬性 def __init__(self, width, height, color): # 添加實例屬性 self.width = width self.height = height self.color = color def __del__(self): print(f'{self}對象已經被刪除') # <__main__.Washer object at 0x000002C8E3429080>對象已經被刪除 haier1 = Washer(100, 300, 'red')
2.6綜合應用
2.6.1烤地瓜
2.6.1.1需求:
需求:
-
被烤的時間和對應的地瓜狀態:
0-3分鐘:生的
3-5分鐘:半生不熟
5-8分鐘:熟的
超過8分鐘:烤糊了
-
添加的調料
用戶可以按自己的意願添加調料
2.6.2步驟分析
需求涉及一個事物: 地瓜,故案例涉及一個類:地瓜類
2.6.2.1定義類
-
地瓜的屬性
-
被烤的時間
-
地瓜的狀態
-
添加的佐料
-
-
地瓜的方法
-
被烤
-
用戶根據意願設定每次烤地瓜的時間
-
判斷地瓜被烤的總時間是在哪個區間,修改地瓜狀態
-
-
添加佐料
-
用戶根據意願設定添加的佐料
-
將用戶添加的佐料存儲
-
-
-
顯示對象信息
2.6.2.2代碼實現
class SweetPotato(): def __init__(self): # 被烤的時間 self.cook_time = 0 # 烤的狀態 self.cook_state = '生的' # 佐料列表 self.condiments = [] def cook(self, time): """烤地瓜方法""" self.cook_time += time if 0 <= self.cook_time < 3: self.cook_state = '生的' elif 3 <= self.cook_time < 5: self.cook_state = '半生不熟的' elif 5 <= self.cook_time < 8: self.cook_state = '熟了的' elif 8 <= self.cook_time: self.cook_state = '糊了的' def __str__(self): return f'這個地瓜烤了{self.cook_time}分鐘,狀態是{self.cook_state},添加的調料有{self.condiments}' def add_condiments(self, condiment): """添加佐料""" self.condiments.append(condiment) digua1 = SweetPotato() print(digua1) digua1.cook(2) digua1.add_condiments('辣椒麪') print(digua1) digua1.cook(2) digua1.add_condiments('食鹽') print(digua1) digua1.cook(2) digua1.add_condiments('孜然粉') print(digua1)
2.7繼承
Python面向對象的繼承指的是多個類之間的所屬關係,即子類默認繼承父類的所有屬性和方法,具體如下:
# 父類A class A(object): def __init__(self): self.num = 1 def info_print(self): print(self.num) # 子類B class B(A): # 空語句,保持程序的完整性 pass result = B() result.info_print() # 1
在Python中,所有類默認繼承object類,object類是頂級類或基類;其他子類叫派生類
2.7.1單繼承
所謂單繼承就是一個類繼承一個父類
# 1.師父類 class Master(object): def __init__(self): self.koufu = '[古法煎餅果子配方]' def make_cake(self): print(f'運用{self.koufu}製作煎餅果子') # 2.徒弟類繼承師父類Master class Prentice(Master): pass # 3.創建對象daqiu daqiu = Prentice() # 4.對象訪問實例屬性 print(daqiu.koufu) daqiu.make_cake()
2.7.2多繼承
所謂多繼承就是一個類同時繼承多個父類
# 1.師父類 class Master(object): def __init__(self): self.kongfu = '[古法煎餅果子配方]' def make_cake(self): print(f'運用{self.kongfu}製作煎餅果子') # 2.學校類 class School(object): def __init(self): self.kongfu = '[蜜汁煎餅果子配方]' def make_cake(self): print(f'運用{self.kongfu}製作煎餅果子') # 2.徒弟類 class Prentice(Master, School): pass # 3.創建對象daqiu daqiu = Prentice() # 4.對象訪問實例屬性 # [古法煎餅果子配方] print(daqiu.kongfu) # 運用[古法煎餅果子配方]製作煎餅果子 daqiu.make_cake()
注意:當一個類有多個父類的時候,默認使用第一個父類的同名屬性和方法
2.7.3子類重寫父類同名方法和屬性
class Master(object): def __init__(self): self.kongfu = '[古法煎餅果子配方]' def make_cake(self): print(f'運用{self.kongfu}製作煎餅果子') class School(object): def __init(self): self.kongfu = '[蜜汁煎餅果子配方]' def make_cake(self): print(f'運用{self.kongfu}製作煎餅果子') class Prentice(Master, School): def __init__(self): self.kongfu = '[獨創煎餅果子配方]' def make_cake(self): print(f'運用{self.kongfu}製作煎餅果子') daqiu = Prentice() print(daqiu.kongfu) daqiu.make_cake() # 類名.__mro__得到該類的繼承關係 print(Prentice.__mro__)
注意:當子類重寫父類的同名屬性和方法時,子類創建對象調用屬性和方法時,調用到的是子類中的同名屬性和方法
2.7.4子類調用父類的同名方法和屬性
class Master(object): def __init__(self): self.kongfu = '[古法煎餅果子配方]' def make_cake(self): print(f'運用{self.kongfu}製作煎餅果子') class School(object): def __init__(self): self.kongfu = '[蜜汁煎餅果子配方]' def make_cake(self): print(f'運用{self.kongfu}製作煎餅果子') class Prentice(Master, School): def __init__(self): self.kongfu = '[獨創煎餅果子配方]' def make_cake(self): # 如果是先調用了父類的屬性和方法,父類屬性會覆蓋子類的屬性,故在調用屬性前,先調用自己子類的初始化 self.__init__() print(f'運用{self.kongfu}製作煎餅果子') def make_master_cake(self): # 如要調用父類的同名方法和屬性,必須先調用__init()方法 Master.__init__(self) Master.make_cake(self) def make_school_cake(self): School.__init__(self) School.make_cake(self) daqiu = Prentice() daqiu.make_cake() daqiu.make_master_cake() daqiu.make_school_cake() daqiu.make_cake()
2.7.5多層繼承
class Master(object): def __init__(self): self.kongfu = '[古法煎餅果子配方]' def make_cake(self): print(f'運用{self.kongfu}製作煎餅果子') class School(object): def __init__(self): self.kongfu = '[蜜汁煎餅果子配方]' def make_cake(self): print(f'運用{self.kongfu}製作煎餅果子') class Prentice(Master, School): def __init__(self): self.kongfu = '[獨創煎餅果子配方]' def make_cake(self): # 如果是先調用了父類的屬性和方法,父類屬性會覆蓋子類的屬性,故在調用屬性前,先調用自己子類的初始化 self.__init__() print(f'運用{self.kongfu}製作煎餅果子') def make_master_cake(self): # 如要調用父類的同名方法和屬性,必須先調用__init()方法 Master.__init__(self) Master.make_cake(self) def make_school_cake(self): School.__init__(self) School.make_cake(self) class Tusun(Prentice): pass daqiu = Tusun() daqiu.make_cake() daqiu.make_master_cake() daqiu.make_school_cake()
2.7.6 super()調用父類方法
class Master(object): def __init__(self): self.kongfu = '[古法煎餅果子配方]' def make_cake(self): print(f'運用{self.kongfu}製作煎餅果子') class School(Master): def __init__(self): self.kongfu = '[蜜汁煎餅果子配方]' def make_cake(self): print(f'運用{self.kongfu}製作煎餅果子') # 2.1super()帶參數寫法 # super(School, self).__init__() # super(School, self).make_cake() # 2.2super()不帶參數寫法 super().__init__() super().make_cake() class Prentice(School): def __init__(self): self.kongfu = '[獨創煎餅果子配方]' def make_cake(self): # 如果是先調用了父類的屬性和方法,父類屬性會覆蓋子類的屬性,故在調用屬性前,先調用自己子類的初始化 self.__init__() print(f'運用{self.kongfu}製作煎餅果子') # 需求:一次性調用父類School,Master的方法 def make_old_cake(self): # 方法一: 如果定義的類名修改,這裏也要修改,麻煩,代碼量大,冗餘 # Master.__init__(self) # Master.make_cake(self) # School.__init__(self) # School.make_cake(self) # 方法二:super() # 方法2.1 super(當前類名,self).函數() # super(Prentice, self).__init__() # super(Prentice, self).make_cake() # 2.2super()不帶參數寫法 super().__init__() super().make_cake() daqiu = Prentice() daqiu.make_old_cake()
2.8私有權限
2.8.1定義私有屬性和方法
在Python中,可以爲實例屬性和方法設置私有權限,即設置某個實例屬性或實例方法不繼承給子類。
設置私有權限的方法:在屬性名和方法名前面加上兩個下劃線__
class Master(object): def __init__(self): self.kongfu = '[古法煎餅果子配方]' def make_cake(self): print(f'運用{self.kongfu}製作煎餅果子') class School(object): def __init__(self): self.kongfu = '[蜜汁煎餅果子配方]' def make_cake(self): print(f'運用{self.kongfu}製作煎餅果子') class Prentice(School, Master): def __init__(self): self.kongfu = '[獨創煎餅果子配方]' # 私有屬性 self.__money = 2000 # 定義私有方法 def __info_print(self): print(self.kongfu) print(self.__money) def make_cake(self): print(f'運用{self.kongfu}製作煎餅果子') class Tusun(Prentice): pass # 對象不能訪問私有屬性和方法 # daqiu = Prentice() # print(daqiu.__money) # daqiu.info_print() # 子類無法繼承父類的私有屬性和私有方法 # xiaoqiu = Tusun() # print(xiaoqiu.__money) # xiaoqiu.__info_print()
2.8.2獲取或修改私有屬性值
在Python中,一般定義函數名get_xx用來獲取私有屬性,定義set_xx用來修改私有屬性值
class Master(object): def __init__(self): self.kongfu = '[古法煎餅果子配方]' def make_cake(self): print(f'運用{self.kongfu}製作煎餅果子') class School(object): def __init__(self): self.kongfu = '[蜜汁煎餅果子配方]' def make_cake(self): print(f'運用{self.kongfu}製作煎餅果子') class Prentice(School, Master): def __init__(self): self.kongfu = '[獨創煎餅果子配方]' self.__money = 2000 # 設置私有屬性值 def set_money(self, money): self.__money = money # 獲取私有屬性值 def get_money(self): return self.__money # 定義私有方法 def __info_print(self): print(self.kongfu) print(self.__money) def make_cake(self): print(f'運用{self.kongfu}製作煎餅果子') class Tusun(Prentice): pass xiaoqiu = Tusun() xiaoqiu.set_money(200000000) print(xiaoqiu.get_money())
2.9面向對象三大特性
-
封裝
-
將屬性和方法書寫到類的裏面的操作即爲封裝
-
封裝可以爲屬性和方法添加私有權限
-
-
繼承
-
子類默認繼承父類的所有屬性和方法
-
子類可以重寫父類的屬性和方法
-
-
多態
-
傳入不同的對象,產生不同的結果
-
2.9.1多態
多態指的是一類事物有多種形態,(一個抽象類有多個子類,因而多態的概念依賴於繼承)
-
定義:多態是一種使用對象的方式,子類重寫父類方法,調用不同子類對象的相同父類方法,可以產生不同的執行結果
-
好處:調用靈活,有了多態,更容易編寫出通用的代碼,做出通用的編程,以適應需求的不斷變化
-
實現步驟:
-
定義父類,並提供公共方法
-
定義子類,並重寫父類方法
-
傳遞子類對象給調用者,可以看到不同子類執行效果不同
-
2.9.2體驗多態
class Dog(object): def work(self): # 父類提供統一方法,哪怕是空方法 pass class ArmyDog(Dog): # 繼承Dog類 def work(self): # 子類重寫父類同名方法 print("追擊敵人...") class DrugDog(Dog): def work(self): print("追查毒品...") class Person(object): def work_with_dog(self, dog): # 傳入不同的對象,執行不同的代碼,即不同的work函數 dog.work() ad = ArmyDog() dd = DrugDog() person = Person() person.work_with_dog(ad) person.work_with_dog(dd)
2.9.3類屬性和實例屬性
2.9.3.1設置和訪問類屬性
-
類屬性就是類對象所擁有的屬性,它被該類的所有實例對象所共有
-
類屬性可以使用類對象或實例對象訪問
class Dog(object): tooth = 10 huahua = Dog() xiaohei = Dog() print(Dog.tooth) # 10 print(huahua.tooth) # 10 print(xiaohei.tooth) # 10
2.9.3.1.2修改類屬性
類屬性只能通過類對象修改,不能通過實例對象修改,如果通過實例對象修改類屬性,表示的是創建一個實例屬性
class Dog(object): tooth = 10 huahua = Dog() xiaohei = Dog() # 修改類屬性 Dog.tooth = 12 print(Dog.tooth) # 12 print(huahua.tooth) # 12 print(xiaohei.tooth) # 12 # 不能通過對象修改屬性,如果這樣操作,實則是創建了一個實例屬性 huahua.tooth = 20 print(Dog.tooth) # 12 print(huahua.tooth) # 20 print(xiaohei.tooth) # 12
2.9.4類方法和靜態方法
2.9.4.1類方法
2.9.4.1.1類方法特點
-
需要用裝飾器
@classmethod
來標識其爲類方法,對於類方法,第一個參數必須是類對象,一般以cls
作爲第一個參數
2.9.4.1.2類方法的使用場景
-
當方法中需要使用類對象(如訪問私有屬性等)時,定義類方法
-
類方法一般和類屬性配合使用
class Dog(object): __tooth = 10 @classmethod def get_tooth(cls): return cls.__tooth wangcai = Dog() result = wangcai.get_tooth() print(result) # 10
2.9.4.2靜態方法
2.9.4.2.1靜態方法特點
-
需要通過裝飾器
@staticmethod
來進行修飾,靜態方法既不需要傳遞類對象也不需要傳遞實例對象(形參沒有self/cls) -
靜態方法也能夠通過實例對象和類對象去訪問
2.9.4.2.2靜態方法使用場景
-
當方法中既不需要使用實例對象(如實例對象,實例屬性),也不需要使用類對象(如類屬性、類方法、創建實例等)時,定義靜態方法
-
取消不需要的參數傳遞,有利於減少不必要的內存佔用和性能消耗
class Dog(object): @staticmethod def info_print(): print("這是一個狗類,用於創建狗實例...") wangcai = Dog() # 靜態方法既可以使用對象訪問又可以使用類訪問 wangcai.info_print() Dog.info_print()
3.異常
3.1瞭解異常
當檢測到一個錯誤時,解釋器無法繼續執行時,反而出現了一些錯誤提示,這就是所謂的“異常”
例如:以r
方式打開一個不存在的文件
open('test.txt', 'r')
D:\software\Python\Python37\python.exe E:/PycharmProjects/Python_Base/Python_Test_1/面向對象.py Traceback (most recent call last): File "E:/PycharmProjects/Python_Base/Python_Test_1/面向對象.py", line 1, in <module> open('test.txt', 'r') FileNotFoundError: [Errno 2] No such file or directory: 'test.txt'
3.2異常的寫法
3.2.1語法
try: 可能發生錯誤的代碼 except: 如果出現異常執行的代碼
3.2.2體驗
需求:嘗試以r
模式打開文件,如果文件不存在,則以w
方式打開
try: f = open('test.txt', 'r') except: f = open('test.txt', 'w') f.close()
3.3捕獲指定異常
3.3.1語法
try: 可能發生錯誤的代碼 except 異常代碼: 如果捕獲到該異常類型執行的代碼
3.3.2體驗
try: print(num) except NameError: print("有錯誤")
注意:
1.如果嘗試執行的代碼的異常類型和要捕獲的異常類型不一致時,則無法捕獲異常
2.一般try下只放一行嘗試執行的代碼
3.4捕獲多個指定異常
當捕獲多個指定異常時,可以把要捕獲的異常類型的名字,放到except後,並使用元組的方式進行書寫
try: print(1/0) except (NameError, ZeroDivisionError): print("有錯誤")
3.5捕獲指定異常描述信息
try: print(1/0) except (NameError, ZeroDivisionError) as result: print(result)
3.6捕獲所有異常
Exception是所有程序異常類的父類
try: print(num) except Exception as result: print(result)
3.7異常的else
else表示的是如果沒有異常要執行的代碼
try: print(1) except Exception as result: print(result) else: print("沒有異常時,執行的代碼")
3.8異常的finally
finally表示的是無論是否異常都要執行的代碼,例如關閉文件
try: f = open('test1.txt', 'r') except: f = open('test1.txt', 'w') else: print("沒有異常,真開心") finally: f.close()
3.9異常的傳遞
體驗異常傳遞
需求:
-
嘗試只讀方式打開test.txt文件,如果文件存在則讀取文件內容,文件不存在則提示用戶即可
-
讀取內容要求:嘗試循環讀取內容,讀取過程中如果檢測到用戶意外終止程序,則
except
捕獲異常並提示用戶
import time try: f = open('test.txt') try: while True: content = f.readline() if len(content) == 0: break time.sleep(2) print(content) except: # 如果在讀取文件的過程中,產生了異常,那麼就會捕獲到 # 比如按下了ctrl+c print("意外終止讀取數據") finally: f.close() print("關閉文件") except: print("文件不存在")
3.10自定義異常
在Python中,拋出自定義異常的語法爲raise 異常對象
需求:密碼長度不足,則報異常(用戶輸入密碼,如果輸入的長度不足3位,則報錯,即拋出自定義異常,並捕獲該異常)
# 自定義異常類,繼承Exception class ShortInputError(Exception): def __init__(self, length, min_len): self.length = length self.min_len = min_len # 設置拋出異常的描述信息 def __str__(self): return f'你輸入的長度是{self.length},不能少於{self.min_len}個字符' def main(): try: con = input("請輸入密碼:") if len(con) < 3: raise ShortInputError(len(con), 3) except Exception as result: print(result) else: print("密碼已經輸入完成") main()
4.模塊和包
4.1模塊
Python模塊(Module),是一個Python文件,以.py
結尾,包含了Python對象定義和Python語句
模塊能定義函數,類和變量,模塊裏也能包含可執行的代碼
4.1.1導入模塊的方式
-
import 模塊名
-
from 模塊名 import 功能名
-
from 模塊名 import *
-
import 模塊名 as 別名
-
from 模塊名 import 功能名 as 別名
4.1.1.1導入方式詳解
1.import
-
語法
# 1.導入模塊 import 模塊名 import 模塊名1,模塊名2... # 不推薦 # 2.調用功能 模塊名.功能名()
-
體驗
import math print(math.sqrt(9))
2.from...import...
-
語法
# 1.導入模塊 from 模塊名 import 功能1, 功能2, 功能3... # 2.調用功能 功能名()
-
體驗
from math import sqrt print(sqrt(9))
3.from...import *
-
語法
# 1.導入模塊 from 模塊名 import * # 2.調用功能 功能名()
-
體驗
from math import * print(sqrt(9))
4.as定義別名
-
語法
# 模塊定義別名 import 模塊名 as 別名 # 功能定義別名 from 模塊名 import 功能 as 別名
-
體驗
# 模塊別名 import time as tt tt.sleep(2) print("hello") # 功能別名 from time import sleep as sl sl(2) print('hello')
4.2製作模塊
在Python中,每個Python中都可以作爲一個模塊,模塊的名字就是文件的名字。也就是說自定義模塊名必須要符合標識符命名規則
4.2.1定義模塊
新建一個Python文件,命名爲my_module1.py
,並定義testA
函數
def testA(a, b): print(a + b)
4.2.2測試模塊
在實際開發中,當一個開發人員編寫完一個模塊後,爲了讓模塊能夠在項目中達到想要的效果,這個開發人員會自行在py文件中添加一些測試信息,例如,在my_module1.py
文件中添加測試代碼
def testA(a, b): print(a + b) # 測試信息 testA(1, 1)
此時,無論是當前文件,還是其他已經導入了該模塊的文件,在運行的時候都會自動執行testA
函數的調用
解決辦法如下:
def testA(a, b): print(a + b) # 只在當前文件調用該函數,其他導入的文件內不符合該條件,則不執行testA函數調用 # __name__是系統變量,是模塊的標識符,值是:如果是自身模塊,值是__main__,否則是當前模塊的名字 if __name__ == '__main__': testA(1, 1)
4.2.3調用模塊
import my_module1 my_module1.testA(2, 2)
4.3模塊定位順序
當導入一個模塊,Python解析器對模塊位置的搜索順序是:
-
當前目錄
-
如果不在當前目錄,Python則搜索在shell變量PYTHONPATH的每個目錄
-
如果都找不到,Python會查看默認目錄。UNIX下,默認路徑一般爲/usr/local/lib/python/
模塊搜素路徑存儲在system模塊的sys.path變量中。變量裏包含當前目錄,PYTHONPATH和由安裝過程決定的默認目錄
-
注意
-
自己的文件名不要和已有模塊名重複,否則導致模塊功能無法使用
-
使用
from 模塊名 import 功能
的時候,如果功能名字重複,調用到的是最後定義或導入的功能
-
4.4__all__
(all列表)
如果一個模塊文件中有__all__
變量,當使用from xxx import *
導入時,只能導入這個列表中的元素
-
my_module1
模塊的代碼
__all__ = ['testA'] def testA(): print('testA') def testB(): print('testB')
-
導入模塊的文件代碼
from my_module1 import * testA() testB()
testA Traceback (most recent call last): File "E:/PycharmProjects/Python_Base/Python_Test_1/1.py", line 3, in <module> testB() NameError: name 'testB' is not defined
4.5包
包將有聯繫的模塊組織在一起,即放到同一個文件夾下,並且在這個文件夾創建一個名字爲__init__.py
文件,那麼這個文件夾就稱之爲包
4.5.1製作包
[New]——[Python Package]——輸入包名——[OK]——新建功能模塊(有聯繫的模塊)
注意:新建包後,包內部會自動創建__init__.py
文件,這個文件控制着包的導入行爲
4.5.1.1快速體驗
-
新建包
mypackage
-
新建包內模塊:
my_module1和my_module2
-
模塊代碼如下
# my_module1 print(1) def info_print1(): print('my_module1')
# my_module2 print(2) def info_print1(): print('my_module2')
4.5.2導入包
4.5.2.1方法一
import 包名.模塊名 包名.模塊名.功能
4.5.2.2體驗
import mypackage.my_module1 mypackage.my_module1.info_print1()
4.5.2.3方法二
注意:必須在__init__.py
文件中添加__all__ = []
,允許控制導入的模塊列表
from 包名 import * 模塊名.目標
4.5.2.4體驗
from mypackage import * my_module1.info_print1()
__init__.py
代碼
__all__ = ['my_module1']