我的python学习之路-装饰器/property/反射
本节内容:
一、装饰器
二、类中的方法
三、property
四、反射
1、反射类中对象的成员
一、装饰器
1. 装饰器的原型
def kuozhan(_func): def newfunc(): print("有房有车的身份:") _func() print("到处张扬:") return newfunc def func(): print("我是高富帅") func=kuozhan(func) func()
2 @语法糖的使用
@符的作用:
(1)自动把@装饰器下面的函数当成参数传递给装饰器
(2)将装饰器返回给新的函数替换旧函数,完成拓展功能
def kuozhan(_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)
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()
@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)
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)
二、类中的方法
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()
三、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)
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)
四、反射
概念: 通过字符串去操作类对象 或者 模块中的属性方法
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("没有该方法")