【问题标题】:Checking whether a function is decorated检查一个函数是否被修饰
【发布时间】:2021-10-05 13:55:45
【问题描述】:

我正在尝试在一个类方法中构建一个控制结构,该方法将函数作为输入,并且如果函数被修饰,则具有不同的行为。关于如何构建函数is_decorated 的任何想法,其行为如下:

def dec(fun):
    # do decoration


def func(data):
    # do stuff


@dec
def func2(data):
    # do other stuff


def is_decorated(func):
    # return True if func has decorator, otherwise False


is_decorated(func)  # False
is_decorated(func2) # True

【问题讨论】:

  • 装饰器只是包装函数的语法糖。
  • @Barmar 好的,然后可能会改写为“您如何编写一个 is_decorated 函数来检测函数是否具有包装函数?”
  • 这似乎是一个 XY 问题。为什么需要区别对待装饰函数?
  • 你可以检查func.__closure__ 是否不是None。包装的函数是一个闭包。
  • 所以你只是想检测你的装饰器,而不是所有的装饰器?

标签: python python-3.x closures decorator python-decorators


【解决方案1】:

是的,这相对容易,因为函数可以添加任意属性,所以装饰器函数可以在做它的时候添加一个:

def dec(fun):
    def wrapped(*args, **kwargs):
        pass

    wrapped.i_am_wrapped = True
    return wrapped

def func(data):
    ... # do stuff

@dec
def func2(data):
    ... # do other stuff

def is_decorated(func):
    return getattr(func, 'i_am_wrapped', False)


print(is_decorated(func))   # -> False
print(is_decorated(func2))  # -> True

【讨论】:

    【解决方案2】:

    一般来说,你不能。留下痕迹的装饰器没有什么特别之处。根据出色的 Primer on Python Decorators 教程,“装饰器提供了一种简单的语法来调用 higher-order functions。”

    教程中的一个快速说明性示例:

    def do_twice(func):
        def wrapper_do_twice():
            func()
            func()
        return wrapper_do_twice
    
    from decorators import do_twice
    
    @do_twice
    def say_whee():
        print("Whee!")
    

    您看到do_twice 内部的wrapper_do_twice 实际上只是调用了两次传递的函数吗?它绝不会修改函数,因此不可能告诉(没有inspection,不要那样做)该函数被修饰了。

    但是,如果您正在编写自己的 装饰器,或者知道您可以利用您正在使用的装饰器正在修改装饰函数(与上面的示例相反,它确实 not 修改函数),那么您可以直接检查是否存在任何标记。有关示例,请参阅this 问题。

    【讨论】:

    • 感谢您的链接,它们很有帮助! :)
    猜你喜欢
    • 1970-01-01
    • 2019-02-11
    • 1970-01-01
    • 2011-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多