Python inspect.getmembers не возвращает фактическую функцию при использовании с декораторами - PullRequest
4 голосов
/ 10 февраля 2012

У меня есть три функции Python:

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

def plain_func(...)

@decorator_func
def wrapped_func(....)

внутри модуля А.

Теперь я хочу получить все функции внутри этого модуля A, для которых я делаю:

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

Проблема здесь в том, что значение func не то, что я хочу.

Это будут decorator_function, plain_func и wrapper (вместо wrapped_func).

Как я могу убедиться, что wrapped_func возвращается вместо обертки?

Ответы [ 2 ]

6 голосов
/ 10 февраля 2012

Вы можете получить доступ к предварительно оформленной функции с помощью:

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 будет украшенной версией.

5 голосов
/ 10 февраля 2012

Если все, что вам нужно, это сохранить оригинальное имя функции видимым "извне", я думаю, что вы можете сделать это с

@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'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...