1.python装饰器的缺点

装饰器可以允许我们在不改变函数或犯方法的调用方式的情况下,添加额外的功能;

如下所示,我们要在中的方法之前增加装饰器check_is_admin,用来判断执行类的方法的用户是否为admin用户;

def check_is_admin(f):
def wrapper(*args,**kwargs):
if kwargs.get('username') != 'admin':
raise Exception("This user is not allowed to get food")
return f(*args,**kwargs)
return wrapper class store(object):
@check_is_admin
def get_food(self,username,food):
return self.storage.get(food) @check_is_admin
def put_food(self,username,food):
self.storage.put(food)

但是,经过装饰器修饰的函数,其func_name和func_doc的属性都会丢失;

如下:

def foobar(username="someone"):
"""Do crzay staff."""
pass
print foobar.func_doc
print foobar.func_name 执行结果为:
Do crzay staff.
foobar

如果给上述函数增加装饰器呢?

def is_admin(f):
def wrapper(*args,**kwargs):
if kwargs.get(*args,**kwargs):
raise Exception("This user is not allowed to get food")
return f(*args,**kwargs)
return wrapper @is_admin
def foobar(username="someone"):
"""Do crazy staff"""
pass
print foobar.__doc__
print foobar.__name__ 执行结果为:
None
wrapper

update_wapper的源码如下:

WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')
WRAPPER_UPDATES = ('__dict__',)
def update_wrapper(wrapper,
wrapped,
assigned = WRAPPER_ASSIGNMENTS,
updated = WRAPPER_UPDATES):
"""Update a wrapper function to look like the wrapped function wrapper is the function to be updated
wrapped is the original function
assigned is a tuple naming the attributes assigned directly
from the wrapped function to the wrapper function (defaults to
functools.WRAPPER_ASSIGNMENTS)
updated is a tuple naming the attributes of the wrapper that
are updated with the corresponding attribute from the wrapped
function (defaults to functools.WRAPPER_UPDATES)
"""
for attr in assigned:
setattr(wrapper, attr, getattr(wrapped, attr))
for attr in updated:
getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
# Return the wrapper so this can be used as a decorator via partial()
return wrapper

  

2.解决方案

使用functools的update_wrapper函数可以解决该问题

如下:

def is_admin(f):
def wrapper(*args,**kwargs):
if kwargs.get(*args,**kwargs):
raise Exception("This user is not allowed to get food")
return f(*args,**kwargs)
return wrapper def foobar(username="someone"):
"""Do crazy staff"""
pass import functools
foobar = functools.update_wrapper(is_admin,foobar)
print foobar.__name__
print foobar.__doc__ 执行结果如下:
foobar
Do crazy staff

但是上述方式手工调用装饰器不太方便,我们在这里使用functools.warps的装饰器

import functools

def is_admin(f):
@functools.wraps(f)
def wrapper(*args,**kwargs):
if kwargs.get(*args,**kwargs):
raise Exception("This user is not allowed to get food")
return f(*args,**kwargs)
return wrapper @is_admin
def foobar(username="someone"):
"""Do crazy staff"""
pass
print foobar.__doc__
print foobar.__name__ 执行结果为:
Do crazy staff #####
foobar

结论:python的装饰器会导致被修饰函数的__doc__,__name__等属性丢掉,如果要保留函数的这些属性,需要在装饰器函数中添加functools.wrap装饰器;

最新文章

  1. JavaScript 智能社 完美运动框架
  2. Sqlserver 中exists 和 in
  3. Eclipse OSGi调试过程
  4. codevs 1227 方格取数 2
  5. 浅析jQuery(function(){})与(function(){})(jQuery)之间的区别
  6. Multiple types were found that match the controller named 'Home'. (weird error)
  7. 菜鸟调错(八)—— Maven编译错误:不兼容的类型的解决方案
  8. node.js乱码问题【WebStorm环境】
  9. Python字符串、元组、列表、字典互相转换的方法
  10. JSP页面批量选择&全选操作&选择回显
  11. C++静态变量对象的建立和删除,兼论MFC开始运行的起点(全局对象)
  12. EnableDocking
  13. 了解ASP.NET 5
  14. C语言 一个数学问题:求s=(a^m)!+(b^n)!
  15. 2440nandflash启动过程再学习
  16. Recurrences UVA - 10870 (斐波拉契的一般形式推广)
  17. Mongodb的下载和安装
  18. Python3 tkinter基础 Canvas create_rectangle 画矩形
  19. python paramiko自动登录网络设备抓取配置信息
  20. Java中同步的几种实现方式

热门文章

  1. OpenJudge Cartesian Tree
  2. 第6章 静态路由和动态路由(4)_OSPF动态路由协议
  3. delphi WebBrowser的使用方法详解(六)
  4. Hbase 分布式环境安装部署
  5. Java 7-Java 循环结构 - for, while 及 do…while
  6. Github上 vue-element-admin项目配置
  7. api文档管理系统合集
  8. 关于微信小程序更新内容后手机上不能及时显示的办法
  9. hadoop2.4的伪集群的搭建
  10. Robot Operating System (ROS)学习笔记4---语音控制