装饰器
装饰器
在不改变原有代码的前提下,为原函数扩展新功能
装饰器的原型
def kuozhan(_func):
def newfunc():
print("厕所前 ... 干净整齐")
_func()
print("厕所后 ... 臭气熏天")
return newfunc
def func():
print("我是屌丝...")
func = kuozhan(func) # func = return 的newfunc func() <=> newfunc()
func()
@的使用
def kuozhan(_func):
def newfunc():
print("厕所前 ... 干净整齐")
_func()
print("厕所后 ... 臭气熏天")
return newfunc
@kuozhan # 执行func = kuozhan(func)
def func():
print("我是屌丝...")
func()

装饰器的嵌套
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()

带有参数的装饰器
"""
原函数和新函数的参数和返回值要保持一一对应
"""
def kuozhan(_func):
def newfunc(who,where,eat):
print("厕所前 ... 文质彬彬")
_func(who,where,eat)
print("厕所后 ... 兽性大发")
return newfunc
@kuozhan
def func(who,where,eat):
print("{who}在{where}吃{eat}".format(who=who,where=where,eat=eat) )
func("假率先","浴缸","榴莲") # <=> newfunc()
带有参数以及返回值的装饰器
def kuozhan(_func):
def newfunc(*args,**kwargs): # 打包成元祖 和 字典
print("手工耿同学向下面拉屎的同学们致敬 ~")
res = _func(*args,**kwargs) # 解包
print("请使用我的自动便便称重器 ... ")
return res
return newfunc
@kuozhan
def func(*args,**kwargs):
dic = {"liuwenbo":"刘文波","zhanglei":"张磊","songjian":"宋健"}
lst = []
try:
i = 0
for k,v in kwargs.items():
# 键在dic中,再去拼凑字符串
if k in dic:
# 人名 + 地点 + 拉的重量
strvar = dic[k] + "在" + args[i] + "拉了" + v
lst.append(strvar)
i += 1
except:
# i会是2 通过dic.values()是一个可迭代对象 迭代key值 寻找 宋健
print("{}找不到拉屎的地点而错,请传入他的拉屎地点".format(list(dic.values())[i]))
return lst
# return ["刘文博在电线杆子下面拉了15吨" , "张磊拉了15斤","宋健拉了15克"]
res = func("电线杆子下面","电影院",liuwenbo="15吨",zhanglei="15斤",songjian="15克")
print(res)
类装饰器的使用
class Kuozhan():
def __call__(self,_func):
return self.kuozhan2(_func)
def kuozhan1(func):
def newfunc():
print("厕所前 ... 饥肠辘辘")
func()
print("厕所后 ... 酒足饭饱")
return newfunc
def kuozhan2(self,func):
def newfunc():
print("厕所前 ... 蓬头垢面")
func()
print("厕所后 ... 衣衫褴褛")
return newfunc
# 方式一 类.扩展函数
@Kuozhan.kuozhan1
def func():
print("厕所进行时 .... ")
func()
print("<===============>")
# 方式二 使用仿函数反弹扩展函数
@Kuozhan() # obj.kuozhan2() -> func = kuozhan2(self,func) = newfunc
def func():
print("厕所进行时 .... ")
func()

带有参数的函数装饰器
def outer(num):
def kuozhan(_func):
def newfunc1(self):
print(self)
print("厕所前 ... 老实巴交")
_func(self)
print("厕所后 ... 浑身哆嗦")
def newfunc2(self):
print(self)
print("厕所前 ... 狂送人头")
_func(self)
print("厕所后 ... 让二追三")
if num == 1:
return newfunc1
elif num == 2:
return newfunc2
elif num == 3:
return "厕所前,洗洗手,厕所后,簌簌口"
return kuozhan
class MyClass():
@outer(1)
# (1) @outer(1) => @kuozhan
# (2) newfunc1 = @kuozhan(func1)
# (3) obj.func1() => obj.newfunc1(self) 因为newfunc1只是一个绑定的函数 所以需要自己传递对象
def func1(self):
print("向前一小步,文明一大步")
@outer(2)
def func2(self):
print("不冲就打包带走")
@outer(3)
def func3(self):
print("请瞄准后发射,尿到外边,说明你短!")
print("<==============>")
obj = MyClass()
obj.func1() # <=> obj.newfunc1()
obj.func2()
print(obj.func3)

带有参数的类装饰器
"""
给修饰的类添加成员属性和方法
"""
class Kuozhan():
# 要添加的成员属性
ad = "贵族茅厕,茅厕中的百岁山."
# 要添加的成员方法
def money(self):
print("贵族茅厕,包月1100,一小时200元")
def __init__(self,num):
self.num = num
def __call__(self,cls): # MyClass
if self.num == 1:
return self.kuozhan1(cls)
elif self.num == 2:
return self.kuozhan2(cls)
# 参数1的情况 : 添加成员属性和方法
def kuozhan1(self,cls):
def newfunc():
cls.ad = Kuozhan.ad
cls.money = Kuozhan.money
return cls()
return newfunc
# 参数2的情况 : 把方法变成属性;
def kuozhan2(self,cls):
def newfunc():
if "run" in cls.__dict__:
cls.run = cls.run() # str
return cls()
return newfunc
# 方式一
@Kuozhan(1) # @obj => @obj(Myclass) => self.kuozhan1(cls) => kuozhan1(self,cls) => newfunc() => return obj
class MyClass():
def run():
return "亢龙有悔"
obj = MyClass()
# kuozhan1(cls) 替换Myclass() 函数替换类 但是类只是一个内存的全局变量的映射 cls 是闭包作用域的 映射 内存中并不消失 见下文
print(obj.ad)
obj.money()
# 方式二
@Kuozhan(2) # @obj => @obj(Myclass) => self.kuozhan1(cls) => kuozhan2(self,cls) => newfunc() => return obj
class MyClass():
def run():
return "亢龙有悔"
obj = MyClass()
print(obj.run) str

其中替换的问题
# (扩展)
虽然MyClass2这个名字替换掉了,但是内存中的该类仍然存在;
class MyClass2():
a = 200
print(id(MyClass2) , "1111111")
def func(cls):
cls.ad = 90
print(id(cls),"22222")
return cls()
obj = func(MyClass2)
MyClass2 = 100
print(MyClass2)
print(obj.a) # 200
print(obj.ad) # 90
"""

浙公网安备 33010602011771号