# ### 装饰器
"""
定义:装饰器用于拓展原来函数功能的一种语法,返回新函数替换旧函数
优点:在不更改原函数代码的前提下 给函数拓展新的功能
语法:@
"""
# 1.装饰器的原型
def kuozhan(func):
def newfunc():
print("厕所前,蓬头垢面")
func()
print("厕所后,容光焕发")
return newfunc
def func():
print("我是高富帅")
func = kuozhan(func) # func = newfunc
func() # newfunc()
# 2.装饰器@符语法
"""
@符有两个作用:
(1)把@符下面的函数当成一个参数传递给装饰器
(2)装饰器经过装饰之后,把新函数返回,让新函数去替换旧函数 (在不改变原有代码的前提下,扩展新功能)
"""
def kuozhan(func):
def newfunc():
print("厕所前,衣衫褴褛")
func()
print("厕所后,光鲜亮丽")
return newfunc
@kuozhan
def func():
print("我是白富美")
func()
# 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()
print("<===============>")
# 4.用装饰器装饰带有参数的函数
"""原函数几个参数,装饰之后就是几个参数,不要乱改"""
def kuozhan(func):
def newfunc(who,where):
print("厕所前,饥饿难耐")
func(who,where)
print("厕所后,满口雌黄,口吐芬芳")
return newfunc
@kuozhan
def func(who,where):
print("{}在{}解手".format(who,where))
func("黄乐锡","鸟窝")
print("<===============>")
# 5.用装饰器装饰带有参数返回值的函数
def kuozhan(func):
# 在定义处 * 和 ** 用来收集,打包
def newfunc(*args,**kwargs):
print("厕所前,萎靡不振")
# 在调用处 * 和 ** 用来打散,解包
res = func(*args,**kwargs)
print("厕所后,兽性大发")
return res
return newfunc
@kuozhan
def func(*args,**kwargs):
dic = {"zyl":"邹永灵","zl":"张龙","zzl":"众赞林"}
strvar = ""
for i in args:
strvar += i + " "
print("解手地点:" + strvar)
# "谁" 留下了"什么"
"""
# 方法一
lst = []
for k,v in kwargs.items():
if k in dic:
res = dic[k] + "留下了" + v + "黄金"
lst.append(res)
"""
# 方法二
lst = [dic[k] + "留下了" + v + "黄金" for k,v in kwargs.items() if k in dic]
return lst
res = func("电影院","水里",zyl="15克",zl="15斤",zzl="15吨",ww="没有")
print(res)
# 6.用类装饰器装饰原函数
class Kuozhan():
# 原函数被func这个形参接收到了
def __call__(self,func):
# 调用一下kuozhan2函数 , 返回newfunc新函数
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 => obj(func) 把对象当成函数使用,触发__call__方法
def func():
print("厕所进行时 ... ")
# func = newfunc
func() # newfunc()
# 7.用带有参数的装饰器装饰原函数
"""为了保留参数n存储的值,在套一层函数形成闭包,延长n的生命周期,供内函数使用"""
def outer(n):
def kuozhan(func):
def newfunc1(self):
print("厕所前,饥肠辘辘1")
func(self)
print("厕所后,呕吐不止1")
def newfunc2(self):
print("厕所前,饥肠辘辘2")
func(self)
print("厕所后,呕吐不止2")
if n == 1:
return newfunc1
elif n == 2:
return newfunc2
elif n == 3:
return 5488
return kuozhan
print("<========================>")
class MyClass():
@outer(1) # @kuozhan
def func1(self):
print("向前一小步,文明一大步")
@outer(2)
def func2(self):
print("来也冲冲,去也冲冲")
@outer(3)
def func3(self):
print("绿巨人觉得还行")
obj = MyClass()
# 扩展原函数新功能
obj.func1() # newfunc1()
obj.func2() # newfunc2()
# 把方法变成属性
print(obj.func3) # func3 = 5488
# 8.用带有参数的类装饰器装饰原函数
"""
如果参数是1,就为当前这个类添加成员属性和方法
如果参数是2,就把当前这个类中的run方法变成属性
"""
class Kuozhan():
ad = "贵族茅厕,欢迎您来,欢迎您再来"
def __init__(self,num):
self.num = num
def money(self):
print("贵族茅厕,每小时收费100,包月1450.")
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():
self.addpty(cls)
# 返回的是对象
return cls()
return newfunc
def addpty(self,cls):
# 为当前cls添加成员属性
cls.ad = Kuozhan.ad
# 为当前cls添加成员方法
cls.money = Kuozhan.money
def kuozhan2(self,cls):
def newfunc():
return self.updatepty(cls) # cls()
return newfunc
def updatepty(self,cls):
if "run" in cls.__dict__:
cls.run = cls.run() # "亢龙有悔"
return cls()
"""
@obj => obj(MyClass) => newfunc @符发动第二次技能,将新函数替换旧函数 MyClass = newfunc
obj = MyClass() <=> newfunc() <=> cls()
obj.ad obj.money()
obj.run = "亢龙有悔"
"""
# 功能一
@Kuozhan(1) # @obj => obj(MyClass) 把对象当成函数使用了,会触发__call__魔术方法
class MyClass():
def run():
return "亢龙有悔"
obj = MyClass()
print(obj.ad)
obj.money()
# 功能二
@Kuozhan(2)
class MyClass():
def run():
return "亢龙有悔"
obj = MyClass()
print(obj.run)
# 扩展1
"""
# 把类当成一个参数传递到函数中,形成一个独立的副本;
class MyClass():
a = 1
def func(cls):
cls.ad = 2
return cls()
obj = func(MyClass)
MyClass = 1
print(MyClass)
print(obj.ad)
# 可以在函数内部创建类,但是作用域只限定在函数的内部,外部不可见;
def func():
class C():
cbb = 10
obj = C()
return obj
obj = func()
print(obj.cbb)
"""