类的装饰器的基本原理
装饰器不仅能装饰函数,也能装饰类
1、装饰器是在不改变源代码,和不改变源函数的调用方式的前提下,给函数增加功能
def deco(func): print("=====") return func def atest(): print("atest函数运行") atest() C:\python35\python3.exe D:/pyproject/day30/类的装饰器.py atest函数运行
比如这个,我想给atest函数增加一个功能
2、在函数中使用装饰器,也可以看之前的学函数的时候的笔记,那个更详细
def deco(func): print("=====") return func @deco #@deco相当于 atest=deco(atest),把atest传给了func, def atest(): print("atest函数运行") atest() C:\python35\python3.exe D:/pyproject/day30/类的装饰器.py ===== atest函数运行
3、在类中使用装饰器
def deco(func): print("=====") return func @deco #@deco 相当于Foo=deco(Foo),把Foo传给了func, class Foo: pass C:\python35\python3.exe D:/pyproject/day30/类的装饰器.py =====
装饰器装饰器,就是把函数或者是类重新装饰一下,在覆盖之前的
@deco 就是 需要装饰的类名/函数名=deco(需要装饰的类名/函数名)
atest=deco(atest)
Foo=deco(Foo)
def deco(obj): print("=====") print(obj)#这个obj就是Foo类,拿到类了,就可以为类赋值了 obj.x = 1 obj.y = 2 obj.z = 3 return obj @deco #@deco 相当于Foo=deco(Foo),把Foo传给了obj class Foo: pass print(Foo.__dict__)#在装饰器里面给类Foo赋值完之后,查看下Foo类的属性字典 C:\python35\python3.exe D:/pyproject/day30/类的装饰器.py ===== <class '__main__.Foo'> {'__doc__': None, '__dict__': <attribute '__dict__' of 'Foo' objects>, 'y': 2, '__module__': '__main__', 'x': 1, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, 'z': 3}
4、同一个装饰器,既可以给class使用,也可以给def函数使用,因为一切皆对象
def deco(obj): print("=====") print(obj)#这个obj就是Foo类,拿到类了,就可以为类赋值了 obj.x = 1 obj.y = 2 obj.z = 3 return obj @deco #装饰类 #@deco 相当于Foo=deco(Foo),把Foo传给了func, class Foo: pass print(Foo.__dict__)#在装饰器里面给类Foo赋值完之后,查看下Foo类的属性字典 @deco #装饰函数 #@deco 相当于atest=deco(atest),把Foo传给了func, def atest(): pass print(atest.__dict__) C:\python35\python3.exe D:/pyproject/day30/类的装饰器.py ===== <class '__main__.Foo'> {'__module__': '__main__', 'x': 1, '__doc__': None, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__dict__': <attribute '__dict__' of 'Foo' objects>, 'z': 3, 'y': 2} ===== <function atest at 0x0000000000A021E0> {'x': 1, 'z': 3, 'y': 2}
5、现在装饰器里面有三个固定的值xyz那么其他的类也用这个装饰器的时候,只想要一个值怎么办呢,如何把这个死的写成活的呢
def deco(obj): obj.x=1 obj.y = 2 obj.z = 3 return obj @deco #@deco相当于Foo=deco(Foo) 就是把Foo重新修饰一下 class Foo: pass @deco #@deco相当于bar=deco(Bar) 就是把Bar重新修饰一下 class Bar: pass print(Bar.z) C:\python35\python3.exe D:/pyproject/day30/类的装饰器修订版.py 3
改成嵌套的
def Typed(**kwargs):#定一个装饰器,要求传入的参数是字典形式 def deco(obj): obj.x=1 obj.y = 2 obj.z = 3 return obj return deco @Typed(x=1,y=2)#Typed(x=1,y=2) 这就是在运行函数Typed,返回值就是deco,这时候的deco是一个局部的 class Foo: pass
在修改下
def Typed(**kwargs):#定一个装饰器,要求传入的参数是字典形式 def deco(obj): print(kwargs)#字典 print("---->",obj)#obj就是Foo return obj print("第一步",kwargs) return deco @Typed(x=1,y=2)#1.Typed(x=1,y=2) 这就是在运行函数Typed,返回值就是deco,这时候的deco是一个局部的 #2.Typed(x=1,y=2)的结果是deco 那么@deco等价于Foo=deco(Foo) class Foo: pass C:\python35\python3.exe D:/pyproject/day30/类的装饰器修订版.py 第一步 {'y': 2, 'x': 1} {'y': 2, 'x': 1} ----> <class '__main__.Foo'>
6、我们的目的是想要多个类都使用这一个装饰器,可以支持传不同的参数,现在类名和字典都动态的传到deco里面了,应该具体如何实现呢
def Typed(**kwargs):#定一个装饰器,要求传入的参数是字典形式 def deco(obj):#Bar传给obj for key,val in kwargs.items():#kwargs.items()是把字典的key和value都取出来 setattr(obj,key,val)#给类Bar设置属性和对应的值 return obj return deco @Typed(x=1,y=2) #1.Typed(x=1,y=2) 这就是在运行函数Typed,返回值就是deco,这时候的deco是一个局部 #2.Typed(x=1,y=2)的结果是deco 那么@deco等价于Foo=deco(Foo) class Foo: print("我是Foo") print(Foo.x) @Typed(name="gouguoqi") #1.先运行Typed(name="gouguoqi"),这就在在运行函数Typed,返回值是deco #2.然后运行@deco,@deco等价于Bar=deco(Bar) class Bar: print("我是Bar") print(Bar.name)#经过装饰以后,Bar已经有了name的属性,所以就取出来了 C:\python35\python3.exe D:/pyproject/day30/类的装饰器修订版.py 我是Foo 1 我是Bar gouguoqi