Как функция может узнать декоратор вызывающей функции
У меня есть два декоратора, @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 не ведет запись этого процесса.