首页 > 代码库 > part 2: decorator装饰器

part 2: decorator装饰器

在之前提到过,装饰器内部的函数已经取代了原有的函数(新的函数),那么这个函数会缺失很多属性

 1 def is_admin(f): 2     def wrapper(*args, **kwargs): 3         if kwargs.get(usrename) != admin: 4             raise Exception("Now allow") 5         return f(*args, **kwargs) 6     return wrapper 7  8 def foobar(username="soneone"): 9     """ DOcarzy stuff """10     pass11 12 13 >>> foobar.func_doc14  DOcarzy stuff 15 >>> foobar.__name__16 foobar17 >>> @is_admin18 def foobar(username="someone"):19     """Do carzy stuff"""20     pass21 22 >>> foobar.__doc__23 >>> foobar.__name__24 wrapper25 >>> 

 

我们可以使用functools来解决

 1 import functools  2 def is_admin(f): 3     @functools.wraps(f) 4     def wrapper(*args, **kwargs): 5         if kwargs.get(usrename) != admin: 6             raise Exception("Now allow") 7         return f(*args, **kwargs) 8     return wrapper 9 10 def foobar(username="soneone"):11     """ DOcarzy stuff """12     pass13 14 15 >>> foobar.__name__16 foobar17 >>> foobar.__doc__18  DOcarzy stuff 19 >>> 

 

在我们的例子当中,我们总是给装饰器函数传入了username关键字作为参数,我们来构建一个更好的方案

inspect

 1 import functools 2 import inspect 3  4 def is_admin(f): 5     @functools.wraps(f) 6     def wrapper(*args, **kwargs): 7  8         func_args = inspect.getcallargs(f,*args,**kwargs) 9         print func_args10         if func_args.get(username) != admin:11             raise Exception("Now allow")12         return f(*args, **kwargs)13     return wrapper14 15 @is_admin16 def foobar(username, type="chocolate"):17     """ DOcarzy stuff """18     pass19 20 >>> foobar(username=admin)21 {username: admin, type: chocolate}22 >>> 

 

part 2: decorator装饰器