封裝python
什麼是封裝 *****安全
封裝的好處 *****框架
函數
什麼是封裝:對外部隱藏內部的屬性,以及實現細節,給外部提供使用的接口
*封裝有隱藏的 意思,但不是單純的隱藏
封裝的目的:限制外部對內部數據的訪問學習
py中 屬性的權限分爲兩種: 1.公開的: 沒有任何限制,誰都能訪問
2.私有的:只有當前類自己可以訪問this
*默認爲公開的spa
爲何要封裝:1.提升安全性 =====>封裝屬性:當這個對象存在一個機密性的屬性。eg: 身份證 不該被外界直接訪問,那就封裝起來設計
2.隔離複雜度=====>封裝方法:一個爲內部提供支持的方法,不該被外界直接訪問,那就封裝起來code
封裝屬性: ```python class Student: def __init__(self,name,age,gender,id_card): self.name = name self.age = age self.gender = gender self.__id_card = id_card def show_id_card(self): # 能夠在這裏添加額外的任何邏輯代碼 來限制外部的訪問 #在類的內部 能夠訪問 print(self.__id_card) ``` 對私有屬性的訪問以及修改 ```python class Student: def __init__(self,name,age,gender,id_card): self.name = name self.age = age self.gender = gender self.__id_card = id_card # 訪問被封裝的屬性 稱之爲訪問器 def get_id_card(self,pwd): # 能夠在這裏添加額外的任何邏輯代碼 來限制外部的訪問 # 在類的內部 能夠訪問 if pwd =="123": return self.__id_card raise Exception("密碼錯誤!") # 修改被封裝的屬性 稱之爲設置器 def set_id_crad(self,new_id): # 身份證必須是字符串類型 # 長度必須是18位 if isinstance(new_id,str) and len(new_id) == 18: self.__id_card = new_id else: raise Exception("身份證號碼 必須是字符串 且長度必須爲18!") ```
什麼樣的方法應該被封裝起來 :一個爲內部提供支持的方法,不該該讓外界直接訪問,就封裝起來
class ATM: def withdraw(self): self.__user_auth() self.__input_money() self.__save_record() # 輸入帳號和密碼 # 顯示餘額 # 輸入取款金額 # 保存記錄 def __user_auth(self): print("請輸入帳號密碼....") def __input_money(self): print("餘額爲100000000,請輸入取款金額!") def __save_record(self): print("記錄流水....")
封裝的原理: py中是經過變形的方式來實現的對象
如何變形:在名稱帶有雙下劃線的變量名字前添加_類名 eg _Person__id_card
經過變形後的名字能夠直接訪問被隱藏的屬性, 但不建議這麼作。變形僅在類的定義階段發生一次,後續再添加的帶有雙下劃線的任何屬性都不會變形, 就是普通屬性
封裝存在的問題:
property的做用 : 將一個方法假裝成普通屬性
why用property:是但願將訪問私有屬性和普通屬性的方式變得一致
setter: 用點語法 給屬性賦值時觸發
deleter:用點語法刪除屬性時觸發
eg:
class Teacher: def __init__(self,name,age,salary): self.name = name self.age = age self.__salary = salary @property # getter # 用於訪問私有屬性的值 也能夠訪問普通屬性 def salary(self): return self.__salary @salary.setter # 用來設置私有屬性的值 也能夠設置普通屬性 def salary(self,new_salary): self.__salary = new_salary @salary.deleter # 用來設置私有屬性的值 也能夠刪除普通屬性 def salary(self): # print("can not delete salary!") del self.__dict__["_Teacher__salary"]
property的另外一種使用場景
計算屬性:一個值它的屬性不是固定死的,而是經過計算動態產生的 eg: BMI
class Person: def __init__(self,name,height,weight): self.name = name self.height = height self.weight = weight # self.BMI = weight / (height ** 2) @property def BMI(self): return self.weight / (self.height ** 2) @BMI.setter def BMI(self,new_BMI): print("BMI 不支持自定義.....") p = Person("egon",1.7,80) print(p.BMI) p.BMI = 10
多態
多態:不是一個具體的技術或代碼,而是指多個不一樣類型對象 能夠相應同一個方法,產生不一樣的結果
生活中能夠理解爲:某種事物具有多個不一樣形態 eg:水: 水的 固液氣 三態
多態帶來的好處:只要學習積累中的方法就行,不須要關心具體的哪一類實現的, 提升靈活性與擴展性
如何實現多態:鴨子類型
class Cat(): def bark(self): print("喵喵喵") def run(self): print("四條腿跑!") def sleep(self): print("趴着睡!") class Pig(): def bark(self): print("哼哼哼!") def run(self): print("四條腿跑!") def sleep(self): print("側躺着睡!") # 一個用來管理動物的方法 只要你傳入是一個動物 我就按照動物的標準來使用 徹底不用考慮你具體是什麼類型 def management_animal(animal): print("==================正在溜%s=============" % animal.__class__.__name__) animal.bark() animal.run() animal.sleep()
鴨子類型就是典型的多態,多種不一樣類型 ,使用方法同樣
__del__:當對象被刪除前會自動調用該方法
何時會刪除對象:i:程序運行結束,解釋器退出 將自動刪除全部數據,
o:手動調用del 時也會刪除對象
* *該函數不是用來刪除對象的
使用場景:當你的對象在建立時,開啓了不屬於解釋器的資源, eg: 打開一個文件
必須保證對象被剷除時 同時關閉額外的資源 eg:文件
它也被稱之爲析構函數 構造的 反義詞 , 構造:是指從無到有 析 構:從有到無,簡單地說就是對象的全部數據所有刪除
__del__通常用於在對象刪除前 作一些清理操做
# 假設要求每個person對象都要綁定一個文件 class Person: def __init__(self,name,path,mode="rt",encoding="utf-8"): self.name = name self.file = open(path,mode,encoding=encoding) # 讀取數據的方法 def read_data(self): return self.file.read() def __del__(self): print("del run!") self.file.close()
__str__:返回對象類型以及地址
在將對象轉爲字符串時執行
**返回值必須爲字符串類型, 子類能夠覆蓋該方法來完成對打印內容的自定義
class Person: def __init__(self,name,age): self.name = name self.age = age # 將對象轉換爲字符串時執行 def __str__(self): print("str run") return "my name is %s , age is %s" % (self.name,self.age) p = Person("rose",20) # print(p) #在打印前都會現將要打印的內容轉爲字符串 經過調用__str__函數 str(p)
反射(檢討,自省)就是經過字符串來操做對象屬性
檢討:是指一個對象必須具有發現自身屬性,以及修改自身屬性的能力。
一個對象在設計初期,可能考慮不周全後期須要刪除或修改已經存在的屬性,和增長屬性
涉及到的方法:hasattr:判斷是否存在某個屬性
getattr:獲取某個屬性的值
setattr:新增或修改某個屬性
delattr:刪除某個屬性
class MY_CMD: def dir(self): os.system("dir") def ipconfig(self): os.system("ipconfig") cmd = MY_CMD() while True: name = input("請輸入要執行的功能:") if hasattr(cmd,name): method = getattr(cmd,name) print(method) method() else: print("sorry this method is not exists....!")
靜態導入:直接寫import的douru 導入方式 前提:提早知道有這個模塊
動態導入:在須要的任什麼時候候 經過指定字符串類型的包名稱來導入須要的模塊
eg:
import importlib
mk = importlib.import_module(m_name)
mk 即導入成功的模塊
where: 經常使用在框架中, 由於框架設計者不可能提早知道後續須要的模塊何類