先说函数的装饰器,如下:
1 def zhuang(func): 2 print("=============") 3 return func # 高阶函数 4 5 6 @zhuang # 相当于是test = zhuang(test) 7 def test(): 8 print("----------------") 9 10 test()
其实所有的@语法糖,都可以像代码中注释的那样等于;类的装饰器与函数装饰器差不多。
1 def zhuang(obj): 2 obj.x = 1 3 obj.y = "age" 4 return obj 5 6 7 @zhuang # 相当于lei = zhuang(lei) 8 class lei: 9 pass 10 11 print(lei.__dict__) #这样写死了,装饰器不管你要不要都给你两个数据属性
上面这样写,显得一点不灵活,在这基础上改进,如下:
1 def typed(**kwargs): 2 def zhuang(obj): 3 # print("=========>", kwargs) # 这里的kwargs是可以传进来的 4 # print('=================',obj) 5 for key,value in kwargs.items(): 6 # obj.__dict__[key] = value # 下面那个与它意思一样,但是不知道为什么不行 7 setattr(obj,key,value) 8 return obj 9 10 # print("--------------", kwargs) 11 return zhuang # 不能加括号 12 13 14 @typed(name = 'wan') # 这里函数名字加()就是运行得返回值,所以第一步:typed(x=1,y=2)----->zhuang 等价于 @zhuang 15 class lei: 16 pass 17 18 19 print(lei.__dict__)
有了类的装饰器有什么用?
比如,可以像下面那样与描述符一起用。
1 # 描述符判断被描述的对象输入的类型是不是想要的类型 2 class miaoshufu: 3 def __init__(self, key, expected_type): 4 self.key = key 5 self.type = expected_type 6 7 def __set__(self, instance, value): 8 if type(value) is self.type: 9 instance.__dict__[self.key] = value 10 else: 11 print("%s传入的类型错误,应该是%s" %(value, self.type)) 12 13 def __get__(self, instance, owner): 14 return instance.__dict__[self.key] 15 16 def __delete__(self, instance): 17 instance.__dict__.pop(self.key) 18 19 20 # 装饰器 21 def Typed(**kwargs): 22 def zhuang(obj): 23 for key,val in kwargs.items(): 24 setattr(obj, key, miaoshufu(key,val)) 25 # key = miaoshufu(str(key), val) 26 return obj 27 return zhuang 28 29 30 @Typed(name = str,age = int) # 不然要写很多,这样减少了重复代码 31 class People: 32 # name = miaoshufu('name', str) 33 # age = miaoshufu('age', int) 34 35 def __init__(self, name, age, salary, height): 36 self.name = name 37 self.age = age 38 self.salary = salary 39 self.height = height 40 41 p = People("wad", "awa", 10000, 173)