zoukankan      html  css  js  c++  java
  • Python全栈day28(类的装饰器)

      类是一个对象也可以像函数一样加装饰器

      类的装饰器.py

    def deco(obj):
        print('======',obj)
        obj.x=1
        obj.y=2
        obj.z=3
        return obj
    
    # @deco  #test=deco(test)
    # def test():
    #     print('test函数运行')
    
    
    #运行了装饰器所以打印了装饰器里面的print内容 @deco #Foo=deco(Foo)
    #====== class Foo: pass
    #打印类的字典,其中xyz属性是在装饰器函数里面定义的 print(Foo.__dict__) #{'__doc__': None, 'z': 3, 'y': 2, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, 'x': 1, '__module__': '__main__'}

      本装饰器就是把类作为实参传递给函数deco然后把返回值赋值给Foo,在装饰器函数里面可以定义对应类的属性

      以上装饰器虽然在装饰器里面实现了对类属性进行赋值但是把赋值写死了

      下面通过嵌套把装饰器写的灵活

      类的装饰器2.py

    #定义装饰器函数deco函数接受参数为字典格式
    def deco(**kwargs):
        def wrapper(obj):
            print('--->',kwargs)
            #---> {'y': 2, 'z': 3, 'x': 1}
            print('类名--->',obj)
            #类名---> <class '__main__.Foo'>
            for key,val in kwargs.items():
                setattr(obj,key,val)
            return obj
        print('===>',kwargs)
        #===> {'y': 2, 'z': 3, 'x': 1}
        return wrapper
    #在原装饰器deco嵌套一个内部函数wrapper
    #执行步骤
    #1,deco(x=1,y=2,z=3)执行函数deco返回的是函数wrapper
    #2,@wrapper装饰类Foo 相当于把类Foo作为参数传递给函数wrapper然后再返回给Foo
    #3,在函数wrapper内部执行对应的对类属性执行赋值操作使用了函数setattr,传递3个参数1位对象2为key3为value
    @deco(x=1,y=2,z=3)  #deco(x=1,y=2,z=3) -->@wrapper
    class Foo:
        pass
    
    
    
    print(Foo.x)
    #1
    
    
    #同理使用装饰器装饰另外一个类可以通过在装饰的时候传递参数实现对不同类装饰的定制
    @deco(name='zhangsan')
    class Bar:
        pass
    
    #装饰成功打印正确
    print(Bar.name)
    #zhangsan

      类的装饰器的应用.py

    class Typed:
        def __init__(self,key,expected_type):
            self.key=key
            self.expected_type=expected_type
        def __get__(self, instance, owner):
            print('get方法')
            # print('instance是[%s]'%instance)
            # print('owner是[%s]'%owner)
            #使用对应的key返回值
            return instance.__dict__[self.key]
    
    
        def __set__(self, instance, value):
            print('set方法')
            #instance就是实例化出来的对象本身
            # print('instance是[%s]'%instance)
            # print('value是[%s]'%value)
            #对应的key进行赋值设置操作
            if not isinstance(value,self.expected_type):
                # print('你输入是不是字符串类型,错误')
                # return
                raise TypeError('%s你传入的不是%s'%(value,self.expected_type))
            instance.__dict__[self.key] = value
    
        def __delete__(self, instance):
            print('delete方法')
            # print('instance是[%s]' % instance)
            #使用对应的key删除操作
            instance.__dict__.pop(self.key)
    
    def deco(**kwargs):
        def wrapper(obj):
            for key,val in kwargs.items():
                print('=====>',key,val)
                #第一次循环key='name' val='str'
                #相当于给类加了对应的类属性设置为描述符
                #完成了之前People类里面的name = Typed('name',str)
                setattr(obj,key,Typed(key,val))
            return obj
        return wrapper
    
    @deco(name=str,age=int)
    class People:
        # name = Typed('name',str)
        # age = Typed('age',int)
        def __init__(self,name,age,salary):
            self.name = name
            self.age = age
            self.salary = salary
    
    p1=People('zhangsan',18,999999)
    print(p1.__dict__)
    

      把之前通过描述符实现的对类型限制的功能使用装饰器实现,简化代码

      使用装饰器来给类属性添加一个属性,只不过这个属性比较特殊,是一个描述符

  • 相关阅读:
    如何为惠普笔记本ProBook 4431S清理电源风扇通风口灰尘
    office app之 Mail App 从新建到发布
    sublime_text3汉化,破解,安装Package_control支持中文显示
    poj3126prime+BFS
    android开发之欢迎界面
    poj 1151 离散化
    DbVisualizer 9 解决中文乱码问题
    RS232、RS422与RS485串口标准简介
    动态创建菜单和动态关联菜单项事件
    更改路径
  • 原文地址:https://www.cnblogs.com/minseo/p/8526782.html
Copyright © 2011-2022 走看看