Python 3.4+inspectфункция
inspect.unwrap()
сигнатуры
Снимает слои декораторов: идёт по цепочке __wrapped__ до последнего объекта и возвращает исходную функцию.
Синтаксис
inspect.unwrap(func, *, stop=None)
Цепочка существует, только если декоратор написан с functools.wraps: без него __wrapped__ нет, и unwrap вернёт обёртку как есть. Параметр stop останавливает спуск на нужном слое — функция-предикат получает каждый объект. Цикл (f.__wrapped__ = f) приводит к ValueError, а не к зависанию. signature() и getsource() уже вызывают unwrap сами; явно он нужен, чтобы добраться до исходной функции, минуя кеш или логирование.
Примеры
import functools, inspect
def cached(fn):
@functools.wraps(fn)
def wrapper(*args):
return fn(*args)
return wrapper
@cached
@cached
def area(w, h):
return w * h
base = inspect.unwrap(area)
print(base is area, base.__name__) # → False area
print(hasattr(base, '__wrapped__')) # → False — это исходная функция
first = inspect.unwrap(area, stop=lambda f: not hasattr(f.__wrapped__, '__wrapped__'))
print(first is area.__wrapped__) # → True — снят один слой
import inspect
def f():
pass
f.__wrapped__ = f
try:
inspect.unwrap(f)
except ValueError as e:
print(type(e).__name__) # → ValueError
См. также
Частые ошибки
Открыть в полном глоссарииdocs.python.orgСообщить о неточности