23.多型 面向物件內建函式 即相關知識
阿新 • • 發佈:2022-03-25
1.多型 概念: 一種事物具備多種不同形態 例如: 水 固態 氣態 液態 大黃蜂:汽車人,汽車,飛機 官方解釋: 多個不同類物件可以響應同一個方法,產生不同的結果 首先強調多型不是一種特殊的語法,而是一種狀態,特性(既多個不同物件可以響應同一個方法,產生不同的結果 ) 既多個物件有相同的使用方法, 好處: 對於使用者而言,大大的降低了使用難度 我們之前寫的USB介面,下的滑鼠,鍵盤,就屬於多型 1.實現多型: # 1.多型性的實現.py 介面 抽象類 鴨子型別 都可以寫出具備多型的程式碼,最簡單的就是鴨子型別23.多型 面向物件內建函式 即相關知識2.oop相關內建函式.py ## isinstance 判斷一個物件是否是某個類的例項 引數1 要判斷的物件 引數2 要判斷的型別 ## issubclass 判斷一個類是否是另一個類的子類 引數一是子類 引數二是父類 3.類中的魔法函式 __str__: 會在物件被轉換為字串時,轉換的結果就是這個函式的返回值 使用場景 :我們可以用函式來自定義, 物件的列印格式 del : 執行時機: 手動刪除物件時立馬執行,或是程式執行結束時也會自動執行 使用場景: 當你的物件在使用的過程中,打開了不屬於直譯器的資源:例如 檔案,網路埠 call : 執行時機:在呼叫物件時自行執行,即物件+() slots :該屬性是一個類屬性,用於優化物件 記憶體佔用,優化的原理,將不固定的屬性數量變得固定,這樣的直譯器就不會為這個物件建立名稱空間,所以__dict__ 也沒了 從而達到節省開銷的效果 4.屬性的 get set 和 del.py getattr : 用於訪問屬性時如果屬性不存在時執行 setattr 用於設定屬性點時 delattr 用del 物件.屬性 刪除屬性時執行 這幾個函式反映了 Python直譯器是 如何實現 用點來訪問屬性 getattribute 該函式也是用來獲取屬性,在獲取屬性時如果存在 getattribute則先執行該函式,如果沒有拿到屬性則繼續呼叫 getattr函式 ,如果拿到了則直接返回5.[] 的 實現原理 getitem setitem delitem 任何的符號,都會被直譯器解釋成特殊含義,例如. [] () getitem 當你用中括號去獲取屬性時執行 setitem 當你用中括號去設定屬性時執行 delitem 當你用中括號刪除屬性時執行 6.運算子過載 當我們在 使用 某個符號時,Python 直譯器 都會為這個符號定義 一個含義,同時呼叫對應的處理函式,當我們需要自定義 物件的 比較規則 時,就可以在子類中 覆蓋 大於 等於 等一系類方法... 案例: 原本自定義物件無法直接使用大於小於來進行比較 ,我們可自定義運算子來實現,讓自定義物件也支援比較運算子 """ 上述程式碼中,other指的是另一個參與比較的物件, 大於和小於只要實現一個即可,符號如果不同 直譯器會自動交換兩個物件的位置 """ 7.迭代器協議: 迭代器是指具有__iter__和__next__的物件 我們可以為物件增加這兩個方法來讓物件變成一個迭代器 8.上下文管理 上下文 context 這個概念屬於語言學科,指的是一段話的意義,要參考當前的場景,既上下文 在 Python中 ,上下文 可以 理解為 是程式碼區間 ,一個範圍 例如with open 開啟的檔案僅在這個上下文中有效 涉及到的兩個方法: enter 表示 進入上下文 (進入某個場景) exit 表示 退出上下文 (退出某個場景) 當執行with 語句時,會先執行enter , 當代碼執行完畢後執行exit,或者程式碼遇到了異常會立即執行exit,並傳入錯誤資訊 包含錯誤的型別.錯誤的資訊.錯誤的追蹤資訊 ps: enter 函式應該返回物件自己 exit函式 可以有返回值,是一個bool型別,用於表示異常是否被處理,僅在上下文中出現異常有用 如果為True 則意味著,異常以及被處理了 False,異常未被處理,程式將中斷報錯 多型 是一種狀態,如果程式具備這種狀態,物件的使用者,可以很方便忽略物件之間的差異 我們可以通過鴨子型別來讓程式具備多型性 一對函式 isinstance 優先 issubclass 優先 類中的魔法函式 str 優先 del 優先 call slots 點語法的 實現 getattr setattr delattr []取值的實現 getitem setitem delitem 運算子過載,可以讓物件具備相互間比較的能力 迭代器的兩個函式 iter next 上下文管理 優先 可以實現自動清理 與del的區別 del管理的是物件的生命週期 會在物件銷燬時執行清理 上下文管理,管理的是一個程式碼範圍 ,出了範圍自動清理
""" 要管理 雞 鴨 鵝 如何能夠最方便的 管理,就是我說同一句話,他們都能理解 他們擁有相同的方法 """ class JI: def bark(self): print("哥哥哥") def spawn(self): print("下雞蛋..") class Duck: def bark(self): print("嘎嘎嘎") def spawn(self): print("下鴨蛋") class E: def bark(self): print("餓餓餓....") def spawn(self): print("下鵝蛋..") j = JI() y = Duck() e = E() def mange(obj): obj.spawn() obj.bark() mange(j) mange(y) mange(e) """ python 中到處都有多型 """ a = 10 b = "10" c = [10] print(type(a)) print(type(b)) print(type(c))1.多型性的實現.py
def add_num(a,b): if isinstance(a,int) and isinstance(b,int): return a+b return None print(add_num(20,10)) class Animal: def eat(self): print("動物的吃東西...") class Pig(Animal): def eat(self): print("豬得吃 豬食....") class Tree: def light(self): print("植物光合作用....") pig = Pig() t = Tree() def manage(obj): if issubclass(type(obj),Animal): obj.eat() else: print("不是動物") # manage(pig) manage(t) # 不是動物 print(issubclass(Tree,object)) # True2.oop相關內建函式.py
import sys import time """ __str__ 物件 轉換 字串 就是 這個函式的返回值 自定義物件的列印格式 """ class Person: def __init__(self,name,age): self.name = name self.age = age def __str__(self): return "這個一個person物件 name:%s age:%s" % (self.name,self.age) def __del__(self): print("del run") p = Person("jack",20) # del p time.sleep(2) print(str(p)) # 這個一個person物件 name:jack age:20 print("over") """del 使用案例""" """ 呼叫del 或者 程式執行結束 """ class FileTool: """ 該類用於簡化檔案的讀寫操作 """ def __init__(self,path): self.file = open(path,'rt',encoding="utf-8") self.a = 100 def read(self): return self.file.read() # 在這裡可以確定一個事,這個物件肯定不使用了 所以可以放心的關閉問檔案了 def __del__(self): self.file.close() tool = FileTool("a.txt") print(tool.read()) """call 呼叫物件 (物件+() 執行)""" class A: def __call__(self,*args,**kwargs): print("call run") print(args) print(kwargs) a = A() a(1,a = 100) """slots 優化記憶體""" class Person: __slots__ = ["name"] def __init__(self,name): self.name = name # print(self.__dict__) p = Person("jac") print(sys.getsizeof(p)) # p.age = 20 # dict 沒有了 print(p.__dict__)3.類中的魔法函式.py
class A: def __setattr__(self, key, value): print(key) print(value) print("__setattr__") self.__dict__[key] = value def __delattr__(self,item): print("__delattr__") print(item) self.__dict__.pop(item) pass def __getattr__(self, item): print("__getattr__") return 1 def __getattribute__(self, item): print("__getattribute__") # return self.__dict__[item] return super().__getattribute__(item) a = A() a.name = "jack" print(a.name) # jack # del a.name # print(a.xxx) # a.name = "xxx" # print(a.name) b = A() b.__dict__["name"] = "jack" print(b.name)4.屬性的 get set 和 del.py
class A: def __getitem__(self,item): print("__getitem__") return self.__dict__[item] def __setitem__(self, key, value): print("__setitem__") self.__dict__[key] = value def __delitem__(self,key): del self.__dict__[key] print("__delitem__") a = A() # # a.name = "jack" a["name"] = "jack" print(a['name']) # del a["name"] # print(a["name"])5.getitem setitem delitem.py
"""""" """ 案例: 原本自定義物件無法直接使用大於小於來進行比較 ,我們可自定義運算子來實現,讓自定義物件也支援比較運算子 """ class Student(object): def __init__(self,name,height,age): self.name = name self.height = height self.age = age def __gt__(self,other): print(self) print(other) print("__gt__") return self.height > other.height def __lt__(self,other): return self.height < other.height def __eq__(self, other): if self.name == other.name and self.age == other.age and self.height == other.height: return True return False stu1 = Student("jack",180,28) stu2 = Student("jack",180,28) print(stu1 < stu2) # False print(stu1 == stu2) """ 上述程式碼中,other指的是另一個參與比較的物件, 大於和小於只要實現一個即可,符號如果不同 直譯器會自動交換兩個物件的位置 """6.物件比較大小.py
# class MyIter: # """ # num 傳入 用來指定迭代次數 # """ # def __init__(self,num): # self.num = num # self.c = 0 # # def __iter__(self): # return self # # def __next__(self): # self.c += 1 # if self.c <= self.num: # return "哈哈" # else: # raise StopIteration # # for i in MyIter(10): # print(i) # for i in range(1,10): # print(i) # for i in [1,2,3,4]: # pass # 實現一個自定義的range class MyRange: def __init__(self,start,end,step): self.start = start self.end = end self.step = step def __iter__(self): return self def __next__(self): a = self.start self.start += self.step if a < self.end: return a else: raise StopIteration for i in MyRange(1,10,2): print(i) """ 1 3 5 7 9 """7.迭代器.py
class MyOpen(object): def __init__(self,path): self.path = path def __enter__(self): self.file = open(self.path) print("enter...") return self def __exit__(self,exc_type,exc_val,exc_tb): print("exit...") print(exc_type,exc_val,exc_tb) self.file.close() return True with MyOpen("a.txt") as m: print(m) print(m.file.read()) "123"+1 """ enter... <__main__.MyOpen object at 0x000001B9A82C45F8> asasasa exit... <class 'TypeError'> must be str, not int <traceback object at 0x000001B9B7382D48> """ # m.file.read()8.上下文管理.py
動態容器實現原理.png