类的装饰器的基本原理

装饰器不仅能装饰函数,也能装饰类

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
posted @ 2018-06-26 10:08  gouguoqi  阅读(582)  评论(0编辑  收藏  举报