閱讀目錄python
一、封裝 二、封裝屬性 三、封裝方法 四、封裝原理 五、property裝飾器 六、多態 七、__str__內置函數 八、__del__內置函數 九、反射 十、動態導入模塊 十一、反射在框架中的應用
##封裝安全
#什麼是封裝? 對外部隱藏內部的屬性,以及實現細節 , 給外部提供使用的接口 注意:封裝有隱藏的意思,但不是單純的隱藏 學習封裝的目的.就是爲了可以限制外界對內部數據的訪問 python中屬性的權限分爲兩種 1.公開的 沒有任何限制 誰都能訪問 2.私有的 只有當前類自己可以訪問 默認爲公共的 #爲何須要封裝 1.提升安全性 封裝屬性 2.隔離複雜度 封裝方法
#一個類中分爲兩種數據,屬性和方法
#如何封裝
__
##封裝屬性框架
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!") # stu1 = Student("rose",20,"man","111111111111111111") # # print(stu1.name) # print(stu1.id_card) # stu1.id_card = "123" # print(stu1.id_card) stu1 = Student("rose",20,"man","111111111111111111") # print(stu1.id_card) # print(stu1.__id_card) # stu1.show_id_card() # stu1.set_id_crad("222222222222222222") # stu1.show_id_card() # id = stu1.get_id_card() # print(id) # stu1.set_id_crad(123) stu1.set_id_crad("555555555555555555") # print(stu1.get_id_card()) print(stu1.get_id_card("1232"))
##封裝方法函數
什麼樣的方法應該被封裝起來 ? 答:一個爲內部提供支持的方法,不該該讓外界直接訪問,那就封裝起來 ,以下例中的 user_auth等... #示例1 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("記錄流水....") atm = ATM() # atm.user_auth() # atm.input_money() # atm.save_record() # atm.withdraw() # atm.save_record()
##封裝原理學習
python是經過 變形的方式來實現的封裝 如何變形 在名稱帶有雙下劃線開頭的變量名字前添加_類名 如_Person__id_card 固然經過變形後的名字能夠直接訪問被隱藏的屬性 但經過不該該這麼作 變形僅在類的定義階段發生一次 後續再添加的帶有雙下劃線的任何屬性都不會變形 就是普通屬性 #示例1 class Person: def __init__(self,name,age,id_card): self.name = name self.age = age self.__id_card = id_card def get_id_card(self): return self.__id_card p = Person("rose",20,"321123123123123123") print(p.name) # p.__id_card = "321" # print(p.__dict__) # print(p._Person__id_card) p.__gender = "man" print(p.__dict__)
##property裝飾器ui
做用: 將一個方法假裝成普通屬性 爲何用 property 但願將訪問私有屬性和普通屬性的方式變得一致 與property相關的 兩個裝飾器 setter 用點語法 給屬性賦值時觸發 deleter 用點語法刪除屬性時觸發 #示例 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"] # del self.__salary #一般property 用於操做私有的屬性 t = Teacher("egon",38,100000) # # print(t.get_salary()) # # t.set_salary(5000) # # print(t.get_salary()) # print(t.name) # 被封裝的屬性在訪問時 須要調用方法 而普通屬性直接點就ok 這樣一來對於對象的使用者而言 # 必須知道要訪問的屬性 是私有的仍是公開 而後調用對於的方法 用起來麻煩 # 此時 咱們的目標是 讓訪問私有屬性 和訪問普通屬性的方式一直 # property 裝飾器 就是用來將一個方法假裝成屬性 # print(t.salary) # t.salary = 500 # print(t.salary) # 刪除對象屬性 # del t.name # # print(t.name) # del t.salary # a = {"name":123} # # a.pop("name") # # del a["name"] # # print(a) del t.salary # # t.del_salary() # t.salary = 1 # # # # print(t.salary) # # del t.salary # t.get_salary() # t.set_salary(800) # t.delete_salary() # t.salary # t.salary = 800 # del t.salary
##property的另外一種使用場景:計算屬性this
什麼是計算屬性 一個屬性 它的值不是固定死的 而是經過計算動態產生的。 例如:BMI指數 #示例1 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.weight = 60 # print(p.BMI) # print(p.get_BMI()) # p.weight = 60 # # print(p.get_BMI()) # # print(p.name) # print(p.get_BMI()) # # print(p.BMI) # p.weight = 60 # print(p.BMI) # p.BMI = 10
##封裝能不能被繼承問題spa
# 被封裝的內容(私有的) 不能夠被繼承 # class A: # __name = "rose" # _A__name # # def __say_hi(self): # print("A say: hi") # class B(A): # def test(self): # # print(super().__name) #_B__name # print(A._A__name) # # pass # b = B() # b.test()
##多態設計
多態不是一個具體的技術 或代碼 指的是 多個不一樣類型對象 能夠響應同一個方法 ,產生不一樣結果 例如 水: 氣態 固態 液態 動物: 人 貓 豬 汽車人: 汽車 飛機 人型 OOP中 標準解釋: 多個不一樣類型對象 能夠響應同一個方法 而且產生不一樣結果 多態的帶來的好處: 只須要學習基類中的使用方法便可, 不須要關心具體的哪個類 以及實現的 以不變應萬變 提升了靈活性 提升擴展性 若是沒有多態 須要分別學習 person cat pig 的不一樣使用方法 這對於使用者而言太麻煩了 如何實現多態: 鴨子類型 就是典型的多態 多種不一樣類型 使用方法同樣 #示例1 class Person(): def bark(self): print("Hello!") def run(self): print("兩條腿跑!") def sleep(self): print("躺着睡!") 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("側躺着睡!") # person1 = Person() # cat1 = Cat() # pig1 = Pig() # person1.sleep() # cat1.sleep() # pig1.sleep()
class Dog:
def bark(self):
print('汪汪汪')
def run(self):
print('四條腿在跑')
def sleep(self):
print('躺着睡')
class Cat:
def bark(self):
print('喵喵喵')
def run(self):
print('四條腿在跑')
def sleep(self):
print('趴着睡')
def manage_animal(animal):
print('========%s====='%animal.__class__.__name__)
animal.bark()
animal.run()
animal.sleep()
dog = Dog()
manage_animal(dog)
cat = Cat()
manage_animal(cat)
繼承:是類與類之間的關係,什麼是什麼的關係,好處是經過繼承可使用父類中的屬性和方法code
封裝:對外部隱藏屬性和實現細節,同時提供調用的接口,目的提升數據的安全度 和隔離複雜度
多態:不一樣類型的對象使用同一方法產生不一樣的結果,好處是學習統一標準,提升靈活性和拓展性
##經常使用的內置函數
#__str__ 類中的__str__ 該方法在object中有定義 默認行爲 返回對象類型以及地址 <__main__.Person object at 0x0000016F450C7390> 在將對象轉爲字符串時執行 注意:返回值必須爲字符串類型 子類能夠覆蓋該方法來完成 對打印內容的自定義 #示例1 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) #__del__ """ __del__ 當對象被刪除前會自動調用 該方法 聲明時候會刪除對象? 1.程序運行結束 解釋器退出 將自動刪除全部數據 2.手動調用del 時也會刪除對象 注意:該函數不是用來刪除對象的 使用場景 當你的對象在建立時,開啓了不屬於解釋器的資源 例如打開了一個文件 必須保證當對象被刪除時 同時關閉額外的資源 如文件 也稱之爲析構函數 構造 的反義詞 構造 指的是從無到有 析構 值從有到無 簡單的說就對象全部數據所有刪除 總結:__del__該函數 用於 在對象刪除前作一些清理操做 """ #示例1 # 假設要求每個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() # p = Person("jack") # a = 10 # f = open("test.txt") # print(f.read()) # f.close() p2 = Person("rose","本週內容") print(p2.read_data())
##反射
#英文中叫檢討 (自省) 面向對象中的檢討 指的是,一個對象必須具有,發現自身屬性,以及修改自身屬性的能力; 一個對象在設計初期,可能考慮不夠周全後期須要刪除或修改已經存在的屬性, 和增長屬性 反射就是經過字符串來操做對象屬性 涉及到的方法: 1、hasattr 判斷是否存在某個屬性 2、getattr 獲取某個屬性的值 3、setattr 新增或修改某個屬性 4、delattr 刪除某個屬性 #示例1 import os class Student: def __init__(self,name): self.name = name stu = Student("rose") # stu.age = 18 # # print(stu.name) # print(hasattr(stu,"name")) print(getattr(stu,"name")) # # setattr(stu,"name","jack") # print(getattr(stu,"name")) # # delattr(stu,"name") # print(stu.name) #示例2 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 稱之爲靜態導入 創建在一個基礎時 提早已經知道有這個模塊 動態導入 指的是 在須要的任什麼時候候 經過指定字符串類型包名稱來導入須要的模塊 import importlib mk = importlib.import_module(m_name) mk 即導入成功的模塊 該方式經常使用在框架中 由於框架設計者不可能提早預知後續須要的模塊和類
動態引入引入一個模塊,name能夠是相對路徑和絕對路徑,若是是相對路徑的話,這package就是相應的包名
#示例 import importlib m_name = input("請輸入要導入的模塊名稱:") #執行要輸入模塊名稱:build_house.core mk = importlib.import_module(m_name) print(mk) from build_house import conf print(conf) 註解:print(mk) 和print(conf) 結果同樣的
##反射在框架中的應用
#core.py文件 import importlib from 代碼.build_house import conf def building(): print("毛坯房建造完成.......") # 讀取用戶提供配置信息 來加載用戶所須要的一系列裝飾品 for cls_info in conf.decorations: # print(cls_info) # 切割類名和模塊路徑 m_name,cls_name = cls_info.rsplit(".",1) # print(m_name,cls_name) # 導入模塊 mk = importlib.import_module(m_name) # print(mk) # 從模塊中獲取類 if not hasattr(mk,cls_name): continue cls = getattr(mk,cls_name) obj = cls() print(obj) building() #conf.py文件 decorations = ["build_house.my_decoration.Table", "build_house.my_decoration.Bed", "build_house.my_decoration.Light", "other_decoration.Sofa"] #my_decoration.py文件 class Table: pass class Light: pass class Bed: pass