day25:7個魔術方法&5個關於類的魔術屬性
- 2020 年 8 月 6 日
- 筆記
- Python全棧31期-筆記
目錄
一個小表格方便記憶哈
__del__ (析構方法)
__del__簡要介紹
1.觸發時機:當對象被內存回收的時候自動觸發
(1)頁面執行完畢回收所有變量
(2)所有對象被del的時候
2.功能:對象使用完畢後資源回收
3.參數:一個self接受對象
4.返回值:無
第一種情況:頁面執行完畢回收所有變量
class LangDog(): food = "改吃蔬菜" def __init__(self, name): self.name = name def __del__(self): print("析構方法被觸發") print("0001=====") obj = LangDog("肉絲") print("0002=====") # 1.頁面執行完畢回收所有變量 print(obj.name) # 當執行完這句話後,才算頁面執行完畢,這個時候觸發__del__析構方法 ''' 運行結果: ===== ===== 肉絲 析構方法被觸發 '''
第二種情況:所有對象被del的時候
如何理解第二種情況中所說到的所有對象?
代碼如下:
class LangDog(): food = "改吃蔬菜" def __init__(self, name): self.name = name def __del__(self): print("析構方法被觸發") obj1 = LangDog("肉絲") obj2 = obj1 print("<=====start=====>") del obj1 print("<=====end=====>")
打印結果:
雖然obj1對象被刪除了,但是obj2對象並沒有被刪除,所以不會觸發析構方法
打印了「析構方法被觸發」是因為整個頁面執行完畢了,也會觸發析構方法
使用__del__模擬文件操作
# 3.模擬文件操作 import os class ReadFile(): def __new__(cls,filename): if os.path.exists(filename): # 判斷文件路徑是否存在 return object.__new__(cls) # 如果文件存在,創建文件對象 else: return print("該文件是不存在的") # 如果文件不存在,給予錯誤提示 def __init__(self,filename): # 打開文件 self.fp = open(filename,mode="r+",encoding="utf-8") def readcontent(self): # 讀取文件 return self.fp.read() def __del__(self): # 關閉文件 self.fp.close() obj = ReadFile("1.txt") if obj is not None: res = obj.readcontent() print(res) else: print("沒有該類文件") # 當然,也可以用三元運算符來實現 """ 真值 if 條件表達式 else 假值 """ print(obj.readcontent()) if obj is not None else print("沒有該類文件")
魔術方法:__str__
__str__簡要介紹
1.觸發時機: 使用print(對象)或者str(對象)的時候觸發
2.功能: 查看對象
3.參數: 一個self接受當前對象
4.返回值: 必須返回字符串類型
class Cat(): gift = "小貓咪會賣萌求貓糧,小貓咪抓老鼠" def __init__(self,name): self.name = name def __str__(self): return self.cat_info() def cat_info(self): return "小貓咪的名字是{},小貓咪{}元".format(self.name,5000) # __repr__ = __str__ tom = Cat("湯姆") # 方法一. print(對象) print(tom) # 方法二. str(對象) res = str(tom) print(res)
魔術方法:__repr__
1.觸發時機: 使用repr(對象)的時候觸發
2.功能: 查看對象,與魔術方法__str__相似
3.參數: 一個self接受當前對象
4.返回值: 必須返回字符串類型
class Mouse(): gift = "偷糧食" def __init__(self,name): self.name = name def __repr__(self): return self.mouse_info() def mouse_info(self): return "名字是{},龍生龍,鳳生鳳,老鼠的兒子會打洞,還會{}".format(self.name,self.gift) # 系統在底層,自動加了一句賦值操作 __str__ = __repr__ jerry = Mouse("傑瑞") res = repr(jerry) print(res) # 因為系統底層賦值的原因,在打印對象或者強轉對象為字符串的時候,仍然可以觸發; print(jerry) res = str(jerry) print(res)
魔術方法:__call__
1.觸發時機:把對象當作函數調用的時候自動觸發
2.功能: 模擬函數化操作
3.參數: 參數不固定,至少一個self參數
4.返回值: 看需求
基本用法
# (1) 基本用法 class MyClass(): a = 1 def __call__(self): print("call魔術方法被觸發了") obj = MyClass() # 實例化一個對象 obj() # 把對象當做函數調用,此時會觸發__call__方法
模擬洗衣服的過程
# (2) 模擬洗衣服的過程 class Wash(): def __call__(self,something): print("我現在要洗{}".format(something)) self.step1() self.step2() self.step3() return "洗完了" def step1(self): print("加熱水,家洗衣粉,加洗衣液,加洗滌劑") def step2(self): print("衣服泡進去攪亂 打散 搓一搓~ ") def step3(self): print("脫水,穿上") obj = Wash() # 方法一 # obj.step1() # obj.step2() # obj.step3() # 方法二 res = obj("衣服") # 把對象obj當做函數進行調用,此時觸發__call__方法,執行__call__方法所有內容 print(res)
模擬內置的int方法,實現相應的操作(有時間再分析)
# (3) 模擬內置int 實現相應的操作 import math class MyInt(): def calc(self,num,sign=1): # print(num,sign) # 去掉左邊多餘的0 strvar = num.lstrip("0") # print(strvar) # 為了防止都是0 ,如果去掉之後為空,返回0 if strvar == "": return 0 # 正常情況下,執行存數字字符串變成數字 , 在乘上相應的符號,得出最後的結果 return eval(strvar) * sign def __call__(self,num): if isinstance(num , bool): if num == True: return 1 elif num == False: return 0 elif isinstance(num,int): return num elif isinstance(num,float): # 方法一 """ strvar = str(num) lst = strvar.split(".") return eval(lst[0]) """ # 方法二 """ if num >= 0: return math.floor(num) else: return math.ceil(num) """ return math.floor(num) if num >= 0 else math.ceil(num) elif isinstance(num,str): if (num[0] == "+" or num[0]== "-") and num[1:].isdecimal(): if num[0] == "+": sign = 1 else: sign = -1 return self.calc(num[1:],sign) elif num.isdecimal(): return self.calc(num) else: return "老鐵,這個真轉不了" myint = MyInt() # myint(5) => 5 # myint(3.14) => 3 res = myint(True) print(res) res = myint(100) print(res) res = myint(3333.14) print(res, type(res)) # 3 # bool int float "12312312323" # int(3.14) => 3 print(int(3.14)) # 3 print(int(-3.14)) # -3 print("<===>") print(myint(3.14)) print(myint(-0.2)) print("<===>") print(int("0000000000000000000000000000000000000000001230000000")) print(int("00000000000000000000000000000000000000000"),"1111222333") print(int("+000000000000000000000000000000000000000000123")) print(int("-000000000000000000000000000000000000000000123")) print(int("000000000000000000000000000000000000000000123")) print("<==111=>") print(myint("+000000000234")) print(myint("000000000000000000000000000000000000000000123")) print(myint("456899200")) print(myint("3.143434")) print(myint(+-++-+-+-+-+-+-+-+-+-+-++++++++-----234234),"<====>") print(int(+-++-+-+-+-+-+-+-+-+-+-++++++++-----234234),"<====>") """ exec("a = 3") print(a) eval("4") """ # print(math.floor(0.14)) # 0 # print(math.floor(3.14)) # 3 # print(math.ceil(-3.14)) # -3
魔術方法:__bool__
__bool__簡要介紹
1.觸發時機:使用bool(對象)的時候自動觸發
2.功能:強轉對象
3.參數:一個self接受當前對象
4.返回值:必須是布爾類型
class MyClass(): def __bool__(self): return False obj = MyClass() res = bool(obj) print(res)
類似的還有如下等等(了解):
__complex__(self) 被complex強轉對象時調用
__int__(self) 被int強轉對象時調用
__float__(self) 被float強轉對象時調用
…
…
魔術方法:__add__,__radd__
__add__簡要介紹
1.觸發時機:使用對象進行運算相加的時候自動觸發
2.功能:對象運算
3.參數:二個對象參數
4.返回值:運算後的值
5.注意點:
對象在加號+的左側時,自動觸發__add__方法
對象在加號+的右側時,自動觸發__radd__方法
加號左側和右側都是對象時,先觸發__add__方法,再觸發__radd__方法
class MyClass1(): def __init__(self,num): self.num = num # 對象在加號+的左側時,自動觸發 def __add__(self,other): # print(self) # print(other) return self.num + other # return 10 + 7 = 17 # 對象在加號+的右側時,自動觸發 def __radd__(self,other): # print(self) # print(other) return self.num * 2 + other # 第一種 a = MyClass1(10) res = a + 7 print(res) # 第二種 b = MyClass1(5) res = 20 + b print(res) # 第三種 print("<============>") res = a+b print(res) """ 第一次觸發魔術方法, a+ =>觸發__add__方法 self => a other => b self.num + other => a.num+ b => 10 + b res = 10 + b 第二次觸發魔術方法 __radd__ self => b other=> 10 self.num * 2 + other => b.num*2 + other => 5 * 2 + 10 => 20 res = 20 """
類似的還有如下等等(了解):
__sub__(self, other) 定義減法的行為:-
__mul__(self, other) 定義乘法的行為:*
__truediv__(self, other) 定義真除法的行為:/
…
…
魔術方法:__len__
__len__簡要介紹
1.觸發時機:使用len(對象)的時候自動觸發
2.功能:用於檢測對象中或者類中成員的個數
3.參數:一個self接受當前對象
4.返回值:必須返回整型
class MyClass(): pty1 = 1 pty2 = 2 __pty3 = 3 pyt3 =10 pty100 = 90 def func1(): pass def __func2(): pass def __func3(): pass def __len__(self): lst = [] dic = MyClass.__dict__ # 方法一 # print(MyClass.__dict__) # 獲取類當中的所有成員 # print(object.__dict__) # 獲取對象中的所有成員 dic = MyClass.__dict__ # 遍歷類中所有成員 for i in dic: # 遍歷類中所有成員 if not(i.startswith("__") and i.endswith("__")): # 如果開頭和結尾都不是以雙下劃線結尾 lst.append(i) # 將符合條件的成員添加到列表中 return len(lst) # 方法二 lst = [i for i in dic if not(i.startswith("__") and i.endswith("__"))] return len(lst)
與類相關的魔術屬性
__dict__ 獲取對象或類的內部成員結構
__doc__ 獲取對象或類的內部文檔
__name__ 獲取類名函數名
__class__ 獲取當前對象所屬的類
__bases__ 獲取一個類直接繼承的所有父類,返回元組
class Man(): pass class Woman(): pass class Children(Man,Woman): """ 功能: 描述小孩天生的屬性 成員屬性:eye , skin 成員方法:skylight , moonread , __makebaby """ eye = "萬花筒血輪眼" skin = "白色" def skylight(self): print("宇智波家族的小孩,天生能夠發動天照技能") def moonread(self,func): # func = func111 print("宇智波家族的小孩,能夠發動月亮的光照消滅你~") res = func.__name__ print(res,type(res)) def __makebaby(self): print("這一手招數,只能我自己用") # __dict__ 獲取對象或類的內部成員結構 obj = Children() print(obj.__dict__) print(Children.__dict__) # __doc__ 獲取對象或類的內部文檔 print(obj.__doc__) print(Children.__doc__) # __name__ 獲取類名函數名 def func111(): print("我是func111方法") # 獲取函數名 obj.moonread(func111) # 獲取類名 obj.moonread(Man) # __class__ 獲取當前對象所屬的類 print(obj.__class__) # __bases__ 獲取一個類直接繼承的所有父類,返回元組 print(Children.__bases__)