Python inspect.getmembers在与装饰器一起使用时不返回实际的函数

Raj*_*jat 5 python decorator inspect

我有三个python函数:

def decorator_function(func)
  def wrapper(..)
    return func(*args, **kwargs)
  return wrapper

def plain_func(...)

@decorator_func
def wrapped_func(....)
Run Code Online (Sandbox Code Playgroud)

在模块A内

现在我想获得这个模块A中的所有函数,我这样做:

for fname, func in inspect.getmembers(A, inspect.isfunction):
  # My code
Run Code Online (Sandbox Code Playgroud)

这里的问题是func的值不是我想要的.

它将是decorator_function,plain_func和wrapper(而不是wrapped_func).

如何确保返回wrapped_func而不是包装?

unu*_*tbu 6

您可以通过以下方式访问预先装饰的功能:

wrapped_func.func_closure[0].cell_contents()
Run Code Online (Sandbox Code Playgroud)

例如,

def decorator_function(func):
  def wrapper(*args, **kwargs):
      print('Bar')
      return func(*args, **kwargs)
  return wrapper   

@decorator_function
def wrapped_func():
    print('Foo')

wrapped_func.func_closure[0].cell_contents()
Run Code Online (Sandbox Code Playgroud)

版画

Foo    # Note, `Bar` was not also printed
Run Code Online (Sandbox Code Playgroud)

但实际上,如果你知道你想要访问预先装饰的功能,那么定义它会更加清晰

def wrapped_func():
    print('Foo')

deco_wrapped_func = decorator_function(wrapped_func)
Run Code Online (Sandbox Code Playgroud)

所以wrapped_func将是预装饰功能, deco_wrapped_func并将是装饰版本.


tom*_*ton 5

如果你想要的只是保持原来的功能名称从"外部"可见,我认为你可以这样做

@functools.wraps
Run Code Online (Sandbox Code Playgroud)

作为装饰的装饰者

这是标准文档中的示例

>>> from functools import wraps
>>> def my_decorator(f):
...     @wraps(f)
...     def wrapper(*args, **kwds):
...         print('Calling decorated function')
...         return f(*args, **kwds)
...     return wrapper
...
>>> @my_decorator
... def example():
...     """Docstring"""
...     print('Called example function')
...
>>> example()
Calling decorated function
Called example function
>>> example.__name__
'example'
>>> example.__doc__
'Docstring'
Run Code Online (Sandbox Code Playgroud)