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__)

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

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

posted @ 2018-03-08 10:10  minseo  阅读(243)  评论(0编辑  收藏  举报