Python装饰器之一

装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。

简单的设计了一个验证权限的装饰器,设计如下

# -*- 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是基于位置的参数还是基于关键字的参数,而是只需要在字典中查询。

Python装饰器之一

相关推荐