检查函数是否被称为装饰器 [英] Check if a function was called as a decorator

查看:59
本文介绍了检查函数是否被称为装饰器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的最小示例中,装饰被调用两次。首先使用 @decorate ,其次通过常规函数调用 decorate(bar)

In the following minimal example decorate is called two times. First using @decorate, second by normal function call decorate(bar).

def decorate(func):
    print(func.__name__)
    return func

@decorate
def bar():
    pass

decorate(bar)

如果通过使用 @decorate 或正常功能调用了调用,是否可以在 decorate 内部看到

Is it possible to see inside of decorate if the call was invoked by using @decorate or as a normal function call?

推荐答案

@decorator 语法只是语法糖,因此这两个示例具有相同的行为。这也意味着您在它们之间所做的任何区分可能都没有您想像的那样有意义。

The @decorator syntax is just syntactic sugar, thus both examples have identical behaviour. This also means whatever distinction you are doing between them might not be as meaningful as you thought.

尽管,您可以使用 inspect 读取脚本并查看上一帧中装饰器的调用方式。

Although, you can use inspect to read your script and see how the decorator was called in the above frame.

import inspect

def decorate(func):
    # See explanation below
    lines = inspect.stack(context=2)[1].code_context
    decorated = any(line.startswith('@') for line in lines)

    print(func.__name__, 'was decorated with "@decorate":', decorated)
    return func

请注意,我们必须为检查指定 context = 2 .stack 函数。 context 参数指示必须返回当前行周围的代码行数。在某些特定情况下,例如装饰子类时,当前行位于类声明上,而不是装饰器上。 在此处已探究了这种行为的确切原因。

Note that we had to specify context=2 to the inspect.stack function. The context argument indicates how many lines of code around the current line must be returned. In some specific cases, such as when decorating a subclass, the current line was on the class declaration instead of the decorator. The exact reason for this behaviour has been explored here.

@decorate
def bar():
    pass

def foo():
    pass
foo = decorate(foo)

@decorate
class MyDict(dict):
    pass



输出



Output

bar was decorated with "@decorate": True
foo was decorated with "@decorate": False
MyDict was decorated with "@decorate": True



Caveat



仍然存在一些难以克服的极端情况,例如装饰器和

Caveat

There are still some corner cases that we can hardly overcome such as linebreaks between the decorator and a class declaration.

# This will fail
@decorate

class MyDict(dict):
    pass

这篇关于检查函数是否被称为装饰器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆