获取 co_names 个函数,而不是 co_names 个装饰器

Get co_names of function, not co_names of decorators

我有一个装饰函数。当我调用 __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']

在调用 .__code__.co_names 以获取函数内部的名称而不是装饰器函数之前,我可以对 foo 做些什么吗?

基本上,我如何先剥离所有装饰器函数?

来自 functools 文档:

To allow access to the original function for introspection and other purposes (e.g. bypassing a caching decorator such as lru_cache()), this function automatically adds a __wrapped__ attribute to the wrapper that refers to the function being wrapped.

所以你可以这样做:

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

这也适用于具有多个装饰器的函数; __wrapped__指的是原来的装饰函数,只要每个装饰器都使用@wraps,所以不需要遵循多个.__wrapped__引用。