Получить co_names функции, а не co_names декораторов - PullRequest
1 голос
/ 06 февраля 2020

У меня есть функция, которая оформлена. Когда я вызываю __call__.co_names, я хочу получить имена, перечисленные в функции, но вместо этого она дает мне имена, перечисленные в декораторе. Позвольте мне показать вам:

from functools import wraps

def decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        baz()
        return func(*args, **kwargs)
    return wrapper

@decorator
def foo():
    bar()

def bar():
    print('bar is the name I want')

def baz():
    print('baz is the name I get')

def foo2():  # undecorated
    bar()

foo.__code__.co_names
# ['baz']

foo2.__code__.co_names
# ['bar']

Могу ли я что-нибудь сделать для foo перед вызовом .__code__.co_names, чтобы получить имена внутри функции, а не функции декоратора?

В принципе, как мне сначала убрать все функции декоратора?

1 Ответ

1 голос
/ 06 февраля 2020

Из документов functools:

Чтобы разрешить доступ к исходной функции для самоанализа и других целей (например, в обход декоратора кэширования, такого как lru_cache()), эта функция автоматически добавляет атрибут __wrapped__ в оболочку, который ссылается на упаковываемую функцию.

Таким образом, вы можете сделать это:

def get_original_function(f):
    return getattr(f, '__wrapped__', f) # default is f, if no __wrapped__ attribute

Это также работает для функций с несколько декораторов; __wrapped__ относится к оригинальной декорированной функции, поскольку каждый из декораторов использует @wraps, поэтому нет необходимости использовать более одной .__wrapped__ ссылки.

...