zoukankan      html  css  js  c++  java
  • [python 基础]python装饰器(一)添加functools获取原函数信息以及functools.partial分析

    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)
  • 相关阅读:
    HDU 2089 不要62
    HDU 5038 Grade(分级)
    FZU 2105 Digits Count(位数计算)
    FZU 2218 Simple String Problem(简单字符串问题)
    FZU 2221 RunningMan(跑男)
    FZU 2216 The Longest Straight(最长直道)
    FZU 2212 Super Mobile Charger(超级充电宝)
    FZU 2219 StarCraft(星际争霸)
    FZU 2213 Common Tangents(公切线)
    FZU 2215 Simple Polynomial Problem(简单多项式问题)
  • 原文地址:https://www.cnblogs.com/halleluyah/p/8821396.html
Copyright © 2011-2022 走看看