简体   繁体   English

如何获得装饰函数的参数规范?

[英]How can I get the argument spec on a decorated function?

I need to determine the argspec (inspect.getargspec) of a function within a decorator: 我需要确定装饰器中函数的argspec(inspect.getargspec):

def decor(func):
    @wraps(func)
    def _decor(*args, **kwargs):
        return func(*args, **kwargs)
    return _decor

@decor
def my_func(key=1, value=False):
    pass

I need to be able to inspect the wrapped "my_func" and return the key/value arguments and their defaults. 我需要能够检查包装的“my_func”并返回键/值参数及其默认值。 It seems that inspect.getargspec doesn't get the proper function. 似乎inspect.getargspec没有得到正确的功能。

(FWIW I need this for some runtime inspection/validation and later documentation generation) (对于一些运行时检查/验证以及后来的文档生成,我需要这个)

If you use Michele Simionato's decorator module to decorate your function, its decorator.decorator will preserve the original function's signature. 如果你使用Michele Simionato的装饰模块来装饰你的函数,它的decorator.decorator将保留原始函数的签名。

import inspect
import decorator

@decorator.decorator
def decor(my_func,*args,**kw):
    result=my_func(*args,**kw)
    return result

@decor
def my_func(key=1, value=False):
    pass
decorated_argspec = inspect.getargspec(my_func)
print(decorated_argspec)
# ArgSpec(args=['key', 'value'], varargs=None, keywords=None, defaults=(1, False))

I've written a simple class that does what you want. 我写了一个简单的课程来做你想要的。 This will achieve the same thing that functools.wraps does as well as preserve the function's signature (from getargspec 's point of view). 这将实现与functools.wraps相同的功能,同时保留函数的签名(从getargspec的角度来看)。 Read the docstring for this class on my gist for more information . 有关详细信息,请阅读我的要点,了解此课程的文档字符串。

Note: this only works on decorating functions and not on class methods. 注意:这仅适用于装饰功能,而不适用于类方法。

import types

class decorator(object):
    def __getattribute__(self, name):
        if name == '__class__':
            # calling type(decorator()) will return <type 'function'>
            # this is used to trick the inspect module >:)
            return types.FunctionType
        return super(decorator, self).__getattribute__(name)

    def __init__(self, fn):
        # let's pretend for just a second that this class
        # is actually a function. Explicity copying the attributes
        # allows for stacked decorators.
        self.__call__ = fn.__call__
        self.__closure__ = fn.__closure__
        self.__code__ = fn.__code__
        self.__doc__ = fn.__doc__
        self.__name__ = fn.__name__
        self.__defaults__ = fn.__defaults__
        self.func_defaults = fn.func_defaults
        self.func_closure = fn.func_closure
        self.func_code = fn.func_code
        self.func_dict = fn.func_dict
        self.func_doc = fn.func_doc
        self.func_globals = fn.func_globals
        self.func_name = fn.func_name
        # any attributes that need to be added should be added
        # *after* converting the class to a function
        self.args = None
        self.kwargs = None
        self.result = None
        self.function = fn

    def __call__(self, *args, **kwargs):
        self.args = args
        self.kwargs = kwargs

        self.before_call()
        self.result = self.function(*args, **kwargs)
        self.after_call()

        return self.result

    def before_call(self):
        pass

    def after_call(self):
        pass

Simply create a new decorator by subclassing 只需通过子类化创建一个新的装饰器

import time

class timeit(decorator):
    def before_call(self):
        self.start = time.time()
    def after_call(self):
        end = time.time()
        print "Function {0} took {1} seconds to complete.".format(
            self.__name__, end - self.start
        )

@timeit
def my_really_cool_function(a, b, c, d='asdf', q='werty'):
    time.sleep(5)

Use it like any normal decorated function 像任何正常的装饰功能一样使用它

args = inspect.getargspec(my_really_cool_function)
print args

my_really_cool_function(1,2,3,4,5)

Output 产量

ArgSpec(args=['a', 'b', 'c', 'd', 'q'], varargs=None,
        keywords=None, defaults=('asdf', 'werty'))
Function my_really_cool_function took 5.0 seconds to complete.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将装饰器中的变量传递给装饰函数中的函数参数? - How can I pass a variable in a decorator to function's argument in a decorated function? 如何查看修饰函数的字节码? - How can I see the bytecode of a decorated function? 如何编写一个可以获取函数或修饰函数的超时装饰器? - How to write a timeout decorator which can get a function or a decorated function? 装饰功能完成后,如何让Python装饰器运行? - How can I get a Python decorator to run after the decorated function has completed? 当我调用内部/装饰函数时,我可以将参数传递给我的装饰器函数吗? - Can I pass an argument into my decorator function when I call the inner/decorated function? 传入装饰的参数 function - Argument passing in decorated function 如何调用njit修饰的function中的jieclass实例? - How can I call a jieclass instance in the function decorated by njit? 如何将参数传递给装饰器,在那里进行处理并转发到装饰函数? - How can I pass arguments to decorator, process there, and forward to decorated function? 是否可以将参数传递给装饰函数? - Is it possible to pass argument to a decorated function? 如何在装饰器中使用 pytest 固定装置而不将其作为装饰 function 的参数 - How to use pytest fixtures in a decorator without having it as argument on the decorated function
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM