[python 基础]python装饰器(一)添加functools获取原函数信息以及functools.partial分析

摘要:
学习Python装饰器时需要注意两点:1.装饰器装饰的函数采用其func_name__和func_func_In doc,我们获得包装函数的文档字符串和名称,而不是修改后的函数wrapsdefcheck_id_Admin:''检查Admin''#__name__和func_文档可以获得函数的原始文档字符串和函数名称,而非与装饰器wrapsdefwrapper:ifkwargs.get相关的@functools!

python装饰器学习的时候有两点需要注意一下

1,被装饰器装饰的函数取其func.__name__和func.func_doc的时候得到的不是被修饰函数的相关信息而是装饰器wrapper函数的docstring和名字

对此我们使用functools这个模块添加一行函数即可

@functools.wraps(f)
def check_id_admin(f):
'''检查是否为admin'''
    # 使得__name__和func_doc能够获得函数原有的docstring和函数名而不是装饰器相关的
    @functools.wraps(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 @check_id_admin def get_food(username,password,food="chocolate"): '''get food''' return "%s get food: %s"%(username,food) def main(): print(get_food.__name__) print(get_food.func_doc)

#输出结果:

  get_food
  get food

 对比不使用@functools.wrap(f)

 wrapper

 none 

2.查看functools.wraps()源码

RAPPER_ASSIGNMENTS = ('__module__', '__name__', '__qualname__', '__doc__',
                       '__annotations__')
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: try:
     #在这里获取原函数wrapped的attr赋值给value value
= getattr(wrapped, attr) except AttributeError: pass else: setattr(wrapper, attr, value) for attr in updated:
     #用wrapped获取的值更新wrapper中的attr getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
# Issue #17482: set __wrapped__ last so we don't inadvertently copy it # from the wrapped function when updating __dict__ wrapper.__wrapped__ = wrapped # Return the wrapper so this can be used as a decorator via partial() return wrapper def wraps(wrapped, assigned = WRAPPER_ASSIGNMENTS, updated = WRAPPER_UPDATES): """Decorator factory to apply update_wrapper() to a wrapper function Returns a decorator that invokes update_wrapper() with the decorated function as the wrapper argument and the arguments to wraps() as the remaining arguments. Default arguments are as for update_wrapper(). This is a convenience function to simplify applying partial() to update_wrapper(). """
return partial(update_wrapper, wrapped=wrapped,
                   assigned=assigned, updated=updated)

从上面代码中可以看出wraps这个函数是通过partial和update_wrapper来实现的

(1)update_wrapper函数

update_wrapper做的工作很简单,就是用参数wrapped表示的函数对象(例如:square)的一些属性()如:__name__、 __doc__)覆盖参数wrapper表示的函数对象的这些相应属性.

即先保存被更新函数信息再更新到新函数中再返回给调用者。

(2)partial函数

简单总结functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。上代码:

from functools import partial

def add(a,b,c):
    return a+b+c
#固定bc两个参数->add_one仅需要一个参数a
add_one = partial(add,b=1,c=3)
#固定a参数->add_two不需要参数运算 add_two
= partial(add_one,a=2) print(add_one(a=3)) print(add_two())

因此

#返回一个参数给定的update_wrapper函数
return
partial(update_wrapper, wrapped=wrapped,assigned=assigned, updated=updated)

免责声明:文章转载自《[python 基础]python装饰器(一)添加functools获取原函数信息以及functools.partial分析》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇function类型(c++11)android UI中添加一张图片如何将这张图片中某一部分设为透明的下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

pycharm快捷键、常用设置、配置管理

http://blog.csdn.net/pipisorry/article/details/39909057 pycharm学习技巧 Learning tips /pythoncharm/help/tip of the day:A special variant of the Code Completion feature invoked by pres...

python直接打印列表

row = [u'课程', u'语文', u'数学', u'英语']print rowprint str(row).decode('unicode-escape')import jsons=json.dumps(row,ensure_ascii=False)print s output: [u'u8bfeu7a0b', u'u8bedu6587', u'u...

guxh的python笔记三:装饰器

1,函数作用域 这种情况可以顺利执行: total = 0 def run(): print(total) 这种情况会报错: total = 0 def run(): print(total) total = 1 这种情况也会报错: total = 0 def run(): total += 1...

ORACLE触发器具体解释

ORACLE PL/SQL编程之八:  把触发器说透    本篇主要内容例如以下: 8.1 触发器类型 8.1.1 DML触发器 8.1.2 替代触发器 8.1.3 系统触发器 8.2 创建触发器 8.2.1 触发器触发次序 8.2.2 创建DML触发器 8.2.3 创建替代(INSTEAD OF)触发器 8.2.3 创建系统事件触发器 8.2.4 系统...

VBScript入门篇

                           VBScript入门篇                                                       作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任。 一.定义一个过程 1 定义一个过程:可以将相同的操作的代码提取出来,方便其他人来调...

Maven--403权限问题解决方式(求解决)

我的程序配置方案例如以下(大牛们相信你们不仅仅是一个传说): 目的:实现maven公布项目到tomcat以下。用eclipse一步到位调试。 pom.xml配置: <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId...