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