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

时间:2012-02-10 02:59:18

标签: python decorator inspect

我有三个python函数:

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

def plain_func(...)

@decorator_func
def wrapped_func(....)

在模块A中。

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

for fname, func in inspect.getmembers(A, inspect.isfunction):
  # My code

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

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

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

2 个答案:

答案 0 :(得分:6)

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

wrapped_func.func_closure[0].cell_contents()

例如,

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()

打印

Foo    # Note, `Bar` was not also printed

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

def wrapped_func():
    print('Foo')

deco_wrapped_func = decorator_function(wrapped_func)

所以wrapped_func将是预先装饰的功能,并且 deco_wrapped_func将是装饰版本。

答案 1 :(得分:5)

如果你想要的是保持原来的功能名称从“外面”可见,我认为你可以用

@functools.wraps

作为装饰者的装饰者

这是标准文档中的示例

>>> 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'