装饰器
定义:装饰器用于扩展原来函数功能的一种语法,返回新函数替换就函数
优点 :在不改变原函数代码的前提下,给函数扩展新的功能
1.装饰器原型
def kuozhan(func): #闭包函数
def newfunc():
print(1111)
func()
print(2222)
return newfunc
def func():
print("我要飞的更高")
func = kuozhan(func)
func()
2.@语法糖的使用
"""
@的两个作用:
1. 自动把@装饰器下面的函数当成参数传递给装饰器
2. 将装饰器返回到新函数替换旧函数,完成功能扩展
"""
def kuozhan(func):
def newfunc():
print("aa")
func()
print("bb")
return newfunc
@kuozhan
def func():
print("遇事不要慌~")
func()
3.装饰器的嵌套
def kuozhan1(func):
def newfunc():
print(11)
func()
print(22)
return newfunc
def kuozhan2(func):
def newfunc():
print("aa")
func()
print("bb")
return newfunc
#从下到上,层层嵌套
@kuozhan1
@kuozhan2
def func():
print("好好学习,天天向上")
func()
4.带有参数的装饰器
"""
原函数有几个参数,新函数就有几个参数
"""
def kuozhan(func):
def newfunc(who,where):#替换的新函数
print(666)
func(who,where)
print(888)
return newfunc
@kuozhan
def func(who,where): #原函数
print("{}在{}".format(who,where))
func("贾英贺","学校")
5.带有参数返回值的装饰器
"""
参数和返回值与原函数保持一致
"""
def kuozhan(func):
def newfunc(*args,**kwargs):#定义处打包成元组,字典
print("床前明月光")
res = func(*args,**kwargs)#调用处解包
print("地上鞋两双")
return res
return newfunc
@kuozhan
def func(*args,**kwargs):
strvar = ""
lst = []
dic = {"ss":"贾英贺","xd":"熊大"}
try: #防止报错
i = 0
for k,v in kwargs.items():
if k =="ss":
strvar = dic[k] + "玩坏{}个{}".format(v,args[i])
elif k == "xd":
strvar = dic[k] + "玩坏{}个{}".format(v,args[i])
else:
strvar = "没有这个人"
lst.append(strvar)
i +=1
except:
print("数据没找到")
lst.append("数据没找到")
return lst
res = func("足球","篮球",xd = 3,ss = 5, jyh = 2)
print(res)
6.类装饰器
class KuoZhan():
def kuozhan1(func):
def newfunc():
print("111")
func()
print("222")
return newfunc
def kuozhan2(self,func):
def newfunc():
print("aaa")
func()
print("bbb")
return newfunc
def __call__(self,func):
return self.kuozhan2(func)
# 方法一:
@KuoZhan.kuozhan1 #使用类本身调用函数
def func():
print("我是单身狗~!")
func()
# 方法二
@KuoZhan() #把对象当成函数调用,自动触发魔术方法__call__ (推荐使用)
def func():
print("谁还不是的孩子")
func()
7.带有参数函数的装饰器
def outer(num):
def kuozhan(func):
def newfunc1(self):
print(111)
func(self)
print(222)
def newfunc2(self):
print(333)
func(self)
print(444)
if num ==1:
return newfunc1
elif num ==2:
return newfunc2
elif num == 3:
return "哈哈哈哈" #把原函数方法变成成员属性
return kuozhan
class My():
@outer(1) #@kuozhan=>func = kuozhan(func)
def func1(self):
print("aaaaaa")
@outer(2)
def func2(self):
print("bbbb")
@outer(3)
def func3(self):
print("ccccc")
obj = My()
obj.func1()
obj.func2()
print(obj.func3)
8.带有参数类的装饰器
"""
1.当参数为1时,为My类添加成员属性和方法
2.当参数为2时,把My类中的run方法变成属性
"""
class Kuo():
ad = 12345
def func(self):
print("小屌丝一个")
def __init__(self,num): #实例化对象触发
self.num = num
def __call__(self,cls): #把对象当函数使用时触发
if self.num ==1:
return self.kuozhan1(cls)
elif self.num == 2:
return self.kuozhan2(cls)
def kuozhan1(self,cls):
def newfunc():
cls.ad = self.ad #为cls类添加成员属性
cls.func = self.func #为cls类添加成员方法
return cls() #返回cls类对象
return newfunc
def kuozhan2(self,cls):
def newfunc():
if "run" in cls.__dict__: #判断类中是否有run成员
cls.run = cls.run(cls()) #把cls类中方法变成属性
return cls() #返回cls类对象
return newfunc
#@obj =>My = obj(My) 触发__call__返回kuozhan1 =>返回newfunc
#所以My = newfunc
#再调用My() 返回My类对象
@Kuo(1)
class My():
def run(self):
print("啥也不是")
obj =My()
obj.func()
print(obj.ad)
@Kuo(2)
class My():
def run(self):
return "我是run~~!"
obj = My()
print(obj.run)