我的python學習之路-裝飾器/property/反射
阿新 • • 發佈:2020-12-24
本節內容:
一、裝飾器
二、類中的方法
三、property
四、反射
1、反射類中物件的成員
一、裝飾器
1. 裝飾器的原型
def kuozhan(_func): def newfunc(): print("有房有車的身份:") _func() print("到處張揚:") return newfunc def func(): print("我是高富帥") func=kuozhan(func) func()
2 @語法糖的使用
@符的作用:
(1)自動把@裝飾器下面的函式當成引數傳遞給裝飾器
(2)將裝飾器返回給新的函式替換舊函式,完成拓展功能
defkuozhan(_func): def newfunc(): print("美麗善良") _func() print("妝容精緻") return newfunc @kuozhan def func(): print("我是白富美") print("------------------") func() # newfunc func = kuozhan(func)= newfunc
3.裝飾器的巢狀
def kuozhan1(_func): def newfunc():print("西裝革履1") _func() print("皮鞋鋥亮2") return newfunc def kuozhan2(_func): def newfunc(): print("美麗善良3") _func() print("妝容精緻4") return newfunc @kuozhan2 @kuozhan1 def func(): print("我是屌絲.....5") func() ## 31524
4. 帶有引數的裝飾器
原函式有幾個引數,新函式就有幾個引數;
def kuozhan(_func): def newfunc(who,where,do): print("結婚之前,一日三餐") _func(who,where,do) print("結婚之後,一日8碗大米飯,為了家庭,日漸消瘦") return newfunc @kuozhan def func(who,where,do): print("{}在{}吃{}".format(who,where,do)) func("李雅琪","電影院","榴蓮") #結婚之前,一日三餐 #李雅琪在電影院吃榴蓮 #結婚之後,一日8碗大米飯,為了家庭,日漸消瘦
5、帶有函式返回值的裝飾器
引數與返回值與原函式保持一致
1 def kuozhan(_func): 2 def func(*args,**kwargs): 3 print("下面是一線城市建築介紹") 4 lst=_func(*args,**kwargs) 5 print("介紹完畢") 6 return lst 7 return func 8 9 10 @kuozhan 11 def func(*args,**kwargs): 12 strvar="" 13 dic={"bj":"北京","sh":"上海","gz":"廣州","sz":"深圳"} 14 lst=[] 15 i=0 16 for k,v in kwargs.items(): 17 if k=="bj": 18 strvar=dic[k]+"的地標建築是"+v+"是"+args[i] 19 elif k=="sh": 20 strvar=dic[k]+"的地標建築是"+v+"是"+args[i] 21 elif k=="gz": 22 strvar=dic[k]+"的地標建築是"+v+"是"+args[i] 23 elif k=="sz": 24 strvar=dic[k]+"的地標建築是"+v+"坐落在"+args[i] 25 else: 26 strvar=k+"查無此出" 27 i+=1 28 lst.append(strvar) 29 return lst 30 31 32 res=func("皇帝的宮殿","電視訊號塔","中國第一","深圳河",bj="故宮",sh="明珠塔",gz="廣州塔",sz="地王大廈") 33 34 print(res)View Code
6、類裝飾器
1 class KuoZhan(): 2 def kuozhan(_func): 3 def newfunc(): 4 print("沒有女朋友之前 .. 快樂的,無拘無束的,拖拖拉拉,很頹廢,很狼狽,很自戀") 5 _func() 6 print("有女朋友之後....很怕黑,愛自拍,換個iphone18,照片都是他") 7 return newfunc 8 9 def __call__(self,_func): 10 return self.kuozhan1(_func) 11 12 13 def kuozhan1(delf,_func): 14 def newfunc(): 15 print("沒有女朋友之前 .. 快樂的,無拘無束的,拖拖拉拉,很頹廢,很狼狽,很自戀") 16 _func() 17 print("有女朋友之後....很怕黑,愛自拍,換個iphone18,照片都是他") 18 return newfunc 19 20 21 ### 方法一 22 @KuoZhan.kuozhan 23 def func(): 24 print("單身進行時....") 25 26 func() 27 28 ### 方法二 29 @KuoZhan() 30 def func(): 31 print("單身進行時....") 32 33 func()View Code
@KuoZhan() 先去執行KuoZhan() 返回物件之後,使用@符發動技能
obj = 類() # 例項化物件
@obj
def func():
pass
@符傳送技能
(1) 把func當成引數傳遞給obj => obj(func)
(2) 把返回的新函式替換舊函式
把物件當成函式呼叫時,自動觸發魔術方法__call__
7、帶有引數的裝飾器
1 def outer(num): 2 def kuozhan(_func): 3 def newfunc1(self): 4 print("廁所前,蓬頭垢面") 5 _func(self) 6 print("廁所後,光彩亮麗") 7 def newfunc2(self): 8 print("遊戲前,瘋狂送人頭") 9 _func(self) 10 print("遊戲後,大殺特殺..") 11 if num ==1: 12 return newfunc1 13 elif num ==2: 14 return newfunc1 15 elif num==3: 16 return "我是最強王者" 17 return kuozhan 18 19 class MyClass(): 20 @outer(1) 21 def func1(self): 22 print("上廁所,來也匆匆,去也匆匆") 23 @outer(2) 24 def func2(self): 25 print("上廁所,上前一小步,文明一大步") 26 @outer(3) 27 def func3(self): 28 print("尿不到坑裡,說明你短") 29 30 31 obj =MyClass() 32 obj.func1() 33 obj.func1() 34 ##把方法變屬性 35 print(obj.func3)View Code
8 、帶有引數類裝飾器
1.當引數為1時,為MyClass 新增屬性和方法
2.當引數為2時,為MyClass 中的run方法變成屬性
1 class KuoZhan(): 2 ad="程式設計師,我們不生產程式碼,我們只做程式碼的搬運工" 3 def money(self): 4 print("程式設計師,基本工資12000,一行程式碼一塊錢") 5 def __init__(self,num): 6 self.num = num 7 def __call__(self,cls): 8 if self.num==1: 9 return self.kuozhan1(cls) 10 elif self.num==2: 11 return self.kuozhan2(cls) 12 def kuozhan1(self,cls): 13 def newfunc(): 14 cls.ad=self.ad 15 cls.money=self.money 16 return cls() 17 return newfunc 18 def kuozhan2(self,cls): 19 def newfunc(): 20 if "run" in cls.__dict__: 21 cls.run=cls.run() 22 return cls() 23 24 return newfunc 25 26 @KuoZhan(1) 27 class MyClass(): 28 def run(): 29 return "亢龍有悔" 30 31 obj =MyClass() 32 print(obj.ad) 33 obj.money() 34 35 @KuoZhan(2) 36 class MyClass(): 37 def run(): 38 return "亢龍有悔" 39 40 41 obj =MyClass() 42 print(obj.run)View Code
二、類中的方法
1、類中的方法的分類
- 無參方法:類中的無參方法只能用類來呼叫
- 繫結方法:(1) 繫結到物件,物件呼叫類中成員方法時,自動傳遞物件引數
- 繫結方法 (2) 繫結到類,物件或者類呼叫類中的成員方法時,自動傳遞類引數
- 靜態方法:無論物件還是引數,系統都不會傳遞任何引數
1 class Cat(): 2 ###無參方法:類中的無參方法只能用類來呼叫 3 def patree(): 4 print("小貓會爬樹") 5 ### 繫結方法:(1) 繫結到物件,物件呼叫類中成員方法時,自動傳遞物件引數 6 def eatfish(self): 7 print("小貓喜歡吃魚") 8 ### 繫結方法 (2) 繫結到類,物件或者類呼叫類中的成員方法時,自動傳遞類引數 9 @classmethod 10 def sleep(cls): 11 print(cls,type(cls)) 12 print("小貓愛睡覺") 13 ## 靜態方法:無論物件還是引數,系統都不會傳遞任何引數 14 @staticmethod 15 def zhualaoshu(): 16 print("小貓愛抓老鼠") 17 18 19 obj = Cat() 20 21 ## 無參方法 22 # obj.patree() # error 23 Cat.patree() 24 25 ###繫結方法: 繫結到物件 26 obj.eatfish() 27 Cat.eatfish(obj) 28 29 ###繫結方法: 繫結到類 30 obj.sleep() # print(obj.__class__) 31 Cat.sleep() # 推薦 32 33 ## 靜態方法 34 obj.zhualaoshu() 35 Cat.zhualaoshu()View Code
三、property
作用:可以把方法變成屬性,動態的控制了該屬性的獲取,設定,刪除三個操作
獲取屬性時自動觸發裝飾器@property
設定屬性時自動觸發裝飾器@username.setter
刪除屬性時自動觸發裝飾器@username.deleter
要求:使用username時,獲取 設定 刪除 函式名必須一致
在函式中去做相應操作
1、應用方式1
1 class MyClass(): 2 def __init__(self,name): 3 self.name = name 4 5 @property 6 def username(self): 7 return self.name 8 9 @username.setter 10 def username(self,val): 11 self.name=val 12 13 @username.deleter 14 def username(self): 15 pass 16 # del self.name 17 18 19 obj = MyClass("張銀") 20 21 # 獲取元素 22 print(obj.username) 23 24 # 設定元素 25 obj.username="家營和" 26 print(obj.name) 27 print(obj.username) 28 29 ## 刪除元素 30 del obj.username 31 print(obj.username)View Code
2、應用方式2
1 class MyClass(): 2 def __init__(self,name): 3 self.name=name 4 ## 獲取元素 5 def get_username(self): 6 return self.name 7 8 ## 設定元素 9 def set_username(self,val): 10 self.name=val 11 12 ## 刪除元素 13 14 def del_username(self): 15 del self.name 16 17 #順序必須按照:獲取方法 -> 設定方法 ->刪除方法 18 username= property( get_username,set_username,del_username) 19 20 21 # 例項化物件 22 obj = MyClass("黃常見") 23 print(obj.name) 24 25 ### 獲取元素username 觸發 get_username方法 26 print(obj.username) 27 28 ### 設定成員usern 觸發set_username方法 29 obj.username ="耿澤師" 30 print(obj.username) 31 32 ### 刪除成員username 觸發del_username 33 del obj.username 34 # print(obj.username)View Code
四、反射
概念: 通過字串去操作類物件 或者 模組中的屬性方法
1、反射類中物件的成員
class Children(): age=1 def __init__(self,name): self.name=name def skin(self): print("孩子面板的顏色取決於人的父母") def eye(self): print("小孩眼睛的顏色是血輪眼") def weight(self): print("小孩的體重不超過一百斤") def __eat(self): print("小孩只能喝奶") obj= Children("小明")
(1)、hasattr() 檢測物件/類是否有指定的成員
判斷的依據:檢視是否可以被呼叫,返回True與False
res = hasattr(obj,"name") res = hasattr(obj,"skin") print(res)
res = hasattr(Children,"name") # False res =hasattr(Children,"skin") # True print(res)
(2) getattr() 獲取物件/類成員的值
res = getattr(obj,"name") ##getattr(類/物件,成員.'預設值防止報錯') res = getattr(obj,"name11","設定友好提示,防止報錯") print(res)
## 通過類來反射[反射出來的是普通函式] func= getattr(Children,"skin") print(func,type(func)) func(obj) ### 通過物件反射[反射出來的是繫結方法] func= getattr(obj,"skin") print(func,type(func)) func()
(3)setattr() 設定物件/類成員的值
setattr(obj,"sex","男性") print(obj.sex) setattr(Children,"school","清華大學") print(obj.school) print(Children.school) setattr(Children,"school", lambda self :print("名牌大學")) obj.school() Children.school(obj) # setattr(obj,"school", lambda :print("名牌大學1")) # obj.school()
(4) delattr() 刪除類/物件的值
delattr(Children,"school") # obj.school() delattr(obj,"name") # print(obj.name)
小例子 : 通過字串操作物件/類中的成員
strvar= input("請告訴我,你想要呼叫的方法是:") if hasattr(obj,strvar): func= getattr(obj,strvar) func() else: print("抱歉 該方法不存在")
2、反射模組中的成員
import sys """ sys.modules 返回的是系統的模組字典""" # print(sys.modules) """ 通過__main__ 字典的鍵,獲取的是當前檔案的模組物件""" # print(sys.modules["__main__"]) modules = sys.modules["__main__"] print(modules) def func1(): print("我是func1") def func2(): print("我是func2") def func3(): print("我是func3") ## 反射模組成員的小例子 while True: func_name = input("請輸入你要使用的方法名>>>") if hasattr(modules,func_name): func = getattr(modules,func_name) func() elif func_name.upper()=="Q": break else: print("沒有該方法")