zoukankan      html  css  js  c++  java
  • 类的装饰器的基本原理

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

    1、装饰器是在不改变源代码,和不改变源函数的调用方式的前提下,给函数增加功能

    def deco(func):
        print("=====")
        return func
    def atest():
        print("atest函数运行")
    atest()
    
    C:python35python3.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:python35python3.exe D:/pyproject/day30/类的装饰器.py
    
    =====
    
    atest函数运行

    3、在类中使用装饰器

    def deco(func):
        print("=====")
        return func
    @deco  #@deco 相当于Foo=deco(Foo),把Foo传给了func,
    class Foo:
        pass
    
    C:python35python3.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:python35python3.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:python35python3.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:python35python3.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:python35python3.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:python35python3.exe D:/pyproject/day30/类的装饰器修订版.py
    
    我是Foo
    
    1
    
    我是Bar
    
    gouguoqi
  • 相关阅读:
    android通过Canvas和Paint截取无锯齿圆形图片
    【转】mysql的cardinality异常,导致索引不可用
    mysql索引无效且sending data耗时巨大原因分析
    linux shell脚本通过参数名传递参数值
    git日志输出格式及两个版本之间差异列表
    jenkins结合ansible用shell实现自动化部署和回滚
    Linux下cp -rf总是提示覆盖的解决办法
    jenkins集成ansible注意事项Failed to connect to the host via ssh.
    ansible操作远程服务器报Error: ansible requires the stdlib json or simplejson module, neither was found!
    利用ssh-copy-id无需密码登录远程服务器
  • 原文地址:https://www.cnblogs.com/gouguoqilinux/p/9227756.html
Copyright © 2011-2022 走看看