python - python 装饰器是否可以根据较早的装饰器结果执行或跳过?

标签 python dependencies decorator execution python-decorators

我从中学到了stack_overflow_entry在 Python 中,装饰器按照它们在源代码中出现的顺序应用。

那么下面的代码片段应该如何表现?

@unittest.skip("Something no longer supported")
@skipIf(not something_feature_enabled, "Requires extra crunchy cookies to run")
def test_this():
  ....

第一个装饰器(如下所示)要求测试运行程序完全跳过test_this()

@unittest.skip("Something no longer supported")

而第二个装饰器则要求测试运行器有条件地跳过运行 test_this()

@skipIf(not Something_feature_enabled,“需要额外的脆 cookies 才能运行”)

那么这是否意味着除非我们首先放置条件跳过装饰器,否则 test_this 根本不会运行?

另外,Python中有没有办法定义装饰器的依赖执行?例如

@skipIf("Something goes wrong")
@skipIf(not something_feature_enabled, "Requires extra crunchy cookies to run")
@log
@send_email
def test_this():
  ....

这个想法是,如果 @skipIf("Something goError"),则启用 @log@send_email 的执行正确

如果我遗漏了一些非常明显的东西,我深表歉意。

最佳答案

我认为您可能错过了一个关键点:装饰器只是一个传递函数并返回函数的函数。

所以,它们是相同的:

@log
def test_this():
    pass

def test_this():
    pass
test_this = log(test_this)

同样:

@skip("blah")
def test_this():
    pass

def test_this():
    pass
test_this = skip("blah")(test_this)

一旦你明白了这一点,你所有的问题就会变得非常简单。


首先,是的,skip(…) 被用来装饰 skipIf(…)(test),所以如果它跳过它所装饰的东西, test 永远不会被调用。


定义装饰器调用顺序的方法是按照您希望调用它们的顺序编写它们。

如果您想动态地执行此操作,则首先可以通过动态应用装饰器来实现。例如:

for deco in sorted_list_of_decorators:
    test = deco(test)

Also, is there any way in Python to define dependent execution of decorators?

不,他们都被处决了。与您所要求的内容更相关的是,每个装饰器都应用于被装饰的函数,而不是装饰器。

但是您始终可以将装饰器传递给条件装饰器:

def decorate_if(cond, deco):
    return deco if cond else lambda f: f

然后:

@skipIf("Something goes wrong")
@decorate_if(something_feature_enabled, log)
@decorate_if(something_feature_enabled, send_email)
def test_this():
    pass

很简单吧?

现在,如果 something_feature_enabled 为 true,则将应用 logsend_email 装饰器;否则,将应用不以任何方式装饰函数并且仅返回原样的装饰器。

但是如果由于函数已经被装饰而无法传递装饰器怎么办?好吧,如果您定义每个装饰器来公开它所包装的函数,那么您始终可以解开它。如果您始终使用 functools.wraps(如果您没有理由不这样做,通常应该这样做 - 即使您有这样的原因,您也可以轻松地以这种方式进行模拟),则包装的函数是始终以 __wrapped__ 形式提供。因此,您可以编写一个装饰器,有条件地轻松删除最外层的装饰:

def undecorate_if(cond):
    def decorate(f):
        return f.__unwrapped__ if cond else f
    return decorate

再说一遍,如果您尝试动态地执行此操作,那么您可能会动态地进行装饰。因此,一个更简单的解决方案是在应用装饰器之前将它们从 decos 可迭代对象中删除,从而跳过您不需要的装饰器。

关于python - python 装饰器是否可以根据较早的装饰器结果执行或跳过?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26746899/

相关文章:

python - 有没有办法使用OpenCV和Python返回图像中不同颜色的像素数量的值

python - 如何在 python 上解决 TISE 的简单边值问题

c# - 使用 SMO DependencyWalker 加载 TreeView

java - 如何让 Maven 依赖于运行时类路径而不是测试类路径?

android - 如何为 Android View 实现装饰器模式

python - 如何模拟装饰函数

python - 对 pandas 数据框进行哈希计算以进行计算列缓存

python - 如果我将脚本命名为 'string.py' 或 'math.py',“导入”操作的行为会有所不同。为什么会这样?

apache - 我可以使用ivy.xml文件中的属性来避免重复依赖性的版本号吗?

javascript - 使用 Promise 或回调时,装饰器函数返回未定义