Как функция может узнать декоратор вызывающей функции

У меня есть два декоратора, @timeout и @retry код, как это

@timeout(seconds=1)
def func_inner(expire):
    time.sleep(expire)

@retry(
    count=2,
    message="Failed command after {expire} seconds",
)
def func(expire):
    func_inner(expire)

Я просто хочу знать, как метод func() может знать, что у func_inner есть декоратор @timeout? Заранее спасибо!

3 ответа

Этот код:

@timeout(seconds=1)
def func_inner(expire):
    time.sleep(expire)

По существу равно:

def func_inner(expire):
    time.sleep(expire)

func_inner = timeout(seconds=1)(func_inner)

метод func просто звонит func_inner(expire), что совпадает с вызовом timeout(seconds=1)(func_inner)(expire) поскольку декоратор переопределил функцию.

Да, вы можете видеть оболочку внутри функции, используя inspect или globals, и можете напрямую обращаться к объекту оболочки.

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

#!/usr/bin/python
import sys
import inspect

def mydecorator(func):
    def mywrapper():
        print( 'in mywrapper' )
        func()
    return mywrapper

@mydecorator
def myfunc():
    felf = globals()[inspect.getframeinfo(inspect.currentframe()).function]
    print("** myfunc inspect : %s"%felf.__name__)

    felf = globals()[sys._getframe().f_code.co_name]
    print("** myfunc globals : %s"%felf.__name__)

    print( 'wrapper =' )
    print( myfunc )

    print( 'done myfunc' )


myfunc()

print( 'wrapper =' )
print( myfunc )

Выше распечатывается,

in mywrapper
** myfunc inspect : mywrapper
** myfunc globals : mywrapper
wrapper =
<function mywrapper at 0x7f30df0e72a8>
done myfunc
wrapper =
<function mywrapper at 0x7f30df0e72a8>

Обратите внимание, что имя - это не имя вашей функции, а оболочка. См. Документацию inspect и getframe для получения дополнительной информации о том, какая информация доступна.

Обнаружение этого было бы возможно только через некоторый определенный механизм, определенный самим декоратором. Декоратор просто берет функцию и возвращает другой объект в общем случае, а сам Python не ведет запись этого процесса.

Другие вопросы по тегам