装饰器本质上是一个Python函数,它可让其余函数在不须要作任何代码变更的前提下增长额外功能,装饰器的返回值也是一个函数对象。它常常用于有切面需求的场景,好比:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,咱们就能够抽离出大量与函数功能自己无关的雷同代码并继续重用。缓存
简单的设计了一个验证权限的装饰器,设计以下app
# -*- coding:utf-8 -*- def check_is_admin(func): def wrapper(*args,**kwargs): if kwargs.get('username') != 'admin': raise Exception('This user is not allowed to get food') return func(*args,**kwargs) return wrapper class Store(object): @check_is_admin def get_food(self,username,food): return self.get(food) @check_is_admin def put_food(self, username, food): return self.put(food) def get(self,food): return food def put(self,food): return food if __name__ == '__main__': s = Store() s.get_food(**{'username':'admin1'},**{'food':'apple'})
到目前为止,咱们的示例中老是假设装饰器有一个名为username的关键字参数传入,可是实际状况并不是如此,因此咱们设计了一个更智能的装饰器,代码以下:函数
# -*- coding:utf-8 -*- import functools,inspect def check_is_admin(func): @functools.wraps(func) def wrapper(*args,**kwargs): func_args = inspect.getcallargs(func,*args,**kwargs) if func_args.get('username') != 'admin': raise Exception('This user is not allowed to get food') return func(*args,**kwargs) return wrapper class Store(object): @check_is_admin def get_food(self,username,food): return self.get(food) @check_is_admin def put_food(self, username, food): return self.put(food) def get(self,food): return food def put(self,food): return food if __name__ == '__main__': s = Store() food = s.get_food(**{'username': 'admin'}, food='apple') print(food)
这里咱们引入了functools,inspect模块。inspect.getcallargs承担了主要工做,它返回一个将参数名字和值做为键值对的字典{'username':'admin','food':'apple'},这就意味着装饰器没必要检查参数username是基于位置的参数仍是基于关键字的参数,而是只须要在字典中查询。性能