函数如何知道其调用函数的装饰器

时间:2019-01-30 01:37:13

标签: python decorator code-inspection

我有两个装饰器,@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 个答案:

答案 0 :(得分:2)

此代码:

@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)相同,因为装饰器已经重新定义了该函数。

答案 1 :(得分:1)

是的,您可以使用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文档。

答案 2 :(得分:0)

只有通过装饰器本身定义的某些特定机制才能检测到它。装饰器仅接受一个函数并在通常情况下返回另一个对象,而Python本身不保留此过程的记录。