Passing default arguments to a decorator in python

廉价感情. 提交于 2019-12-12 07:28:06

问题


I am trying to find a way to pass my functions default arguments to the decorator. I have to say I am fairly new to the decorator business, so maybe I just don't understand it properly, but I have not found any answers yet.

So here my modified example from the python functools.wraps manual page.

from functools import wraps
def my_decorator(f):
    @wraps(f)
    def wrapper(*args, **kwds):
            print 'Calling decorated function'
            print 'args:', args 
            print 'kwargs:', kwds   
            return f(*args, **kwds)
    return wrapper

@my_decorator
def example(i, j=0):
    """Docstring"""
    print 'Called example function'

example(i=1)

I want the j=0 to be passed, too. So that the output should be:

Calling decorated function
args: ()
kwargs: {'i': 1, 'j': 0}
Called example function

回答1:


You can get default argument values by using __defaults__ special attribute.

def my_decorator(f):
@wraps(f)
def wrapper(*args, **kwds):
    print('def args values', f.__defaults__)
    return f(*args, **kwds)
return wrapper

Reference: look for __defaults__ in https://docs.python.org/3/reference/datamodel.html#the-standard-type-hierarchy

A tuple containing default argument values for those arguments that have defaults, or None if no arguments have a default value




回答2:


Default argument is part of function signature. Its not exists in decorator call.

So to use it in wrapper you need to get it out like shown in this question.

import inspect
from functools import wraps

def get_default_args(func):
    signature = inspect.signature(func)
    return {
        k: v.default
        for k, v in signature.parameters.items()
        if v.default is not inspect.Parameter.empty
    }

def my_decorator(f):
    @wraps(f)
    def wrapper(*args, **kwds):
            print('Calling decorated function')
            print('args:', args)
            kwargs = get_default_args(f)
            kwargs.update(kwds)
            print('kwargs:', kwargs)
            return f(*args, **kwds)
    return wrapper

@my_decorator
def example(i, j=0):
    """Docstring"""
    print('Called example function')

example(i=1)

Output:

Calling decorated function
args: ()
kwargs: {'i': 1, 'j': 0}
Called example function


来源:https://stackoverflow.com/questions/31728346/passing-default-arguments-to-a-decorator-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!