Decorators with parameters?

前端 未结 13 1447
我在风中等你
我在风中等你 2020-11-21 22:58

I have a problem with the transfer of variable \'insurance_mode\' by the decorator. I would do it by the following decorator statement:

@execute_complete_rese         


        
13条回答
  •  时光取名叫无心
    2020-11-21 23:33

    Edit : for an in-depth understanding of the mental model of decorators, take a look at this awesome Pycon Talk. well worth the 30 minutes.

    One way of thinking about decorators with arguments is

    @decorator
    def foo(*args, **kwargs):
        pass
    

    translates to

    foo = decorator(foo)
    

    So if the decorator had arguments,

    @decorator_with_args(arg)
    def foo(*args, **kwargs):
        pass
    

    translates to

    foo = decorator_with_args(arg)(foo)
    

    decorator_with_args is a function which accepts a custom argument and which returns the actual decorator (that will be applied to the decorated function).

    I use a simple trick with partials to make my decorators easy

    from functools import partial
    
    def _pseudo_decor(fun, argument):
        def ret_fun(*args, **kwargs):
            #do stuff here, for eg.
            print ("decorator arg is %s" % str(argument))
            return fun(*args, **kwargs)
        return ret_fun
    
    real_decorator = partial(_pseudo_decor, argument=arg)
    
    @real_decorator
    def foo(*args, **kwargs):
        pass
    

    Update:

    Above, foo becomes real_decorator(foo)

    One effect of decorating a function is that the name foo is overridden upon decorator declaration. foo is "overridden" by whatever is returned by real_decorator. In this case, a new function object.

    All of foo's metadata is overridden, notably docstring and function name.

    >>> print(foo)
    .ret_fun at 0x10666a2f0>
    

    functools.wraps gives us a convenient method to "lift" the docstring and name to the returned function.

    from functools import partial, wraps
    
    def _pseudo_decor(fun, argument):
        # magic sauce to lift the name and doc of the function
        @wraps(fun)
        def ret_fun(*args, **kwargs):
            #do stuff here, for eg.
            print ("decorator arg is %s" % str(argument))
            return fun(*args, **kwargs)
        return ret_fun
    
    real_decorator = partial(_pseudo_decor, argument=arg)
    
    @real_decorator
    def bar(*args, **kwargs):
        pass
    
    >>> print(bar)
    
    

提交回复
热议问题