Как функция может узнать декоратор вызывающей функции - PullRequest
0 голосов
/ 30 января 2019

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

@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 ]

0 голосов
/ 30 января 2019

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

0 голосов
/ 30 января 2019

Да, вы можете видеть оболочку внутри функции, используя 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 для получения дополнительной информации о том, какая информация доступна.

0 голосов
/ 30 января 2019

Этот код:

@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), так какДекоратор переопределил функцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...