我从这个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()
而第二个修饰符则要求测试运行程序有条件地跳过运行test_this()
。在
@skipIf(not something_feature_enabled, "Requires extra crunchy cookies to run")
那么这是否意味着test_this
将根本不运行,除非我们将条件跳过修饰符放在第一位?在
另外,在Python中有没有方法定义decorator的依赖执行?e、 g
@skipIf("Something goes wrong")
@skipIf(not something_feature_enabled, "Requires extra crunchy cookies to run")
@log
@send_email
def test_this():
....
其思想是在@skipIf("Something goes wrong")
是true
时启用@log
和{
抱歉,如果我错过了一些非常明显的东西。在
我认为您可能遗漏了一个关键点:decorator只是一个函数,它传递一个函数并返回一个函数。在
所以,这些是相同的:
同样地:
^{pr2}$一旦你明白了这一点,你所有的问题都变得相当简单。在
首先,是的,
skip(…)
被用来修饰skipIf(…)(test)
,因此如果它跳过它所修饰的内容,test
将永远不会被调用。在定义调用decorator的顺序的方法是按照您希望调用它们的顺序编写它们。在
如果您想动态地这样做,那么首先应该动态地应用decorators。例如:
不,他们都会被处死。与您的请求更相关的是,每个decorator被应用于decorated函数,而不是decorator。在
但您总是可以将decorator传递给条件decorator:
然后:
很简单,对吧?在
现在,如果
something_feature_enabled
是真的,则应用log
和send_email
修饰符;否则,将应用一个不以任何方式修饰函数而只返回未更改的函数的装饰器。在但是如果你不能通过decorator,因为函数已经被修饰了呢?好吧,如果您定义每个decorator来公开它包装的函数,那么您总是可以展开它。如果您总是使用
functools.wraps
(如果您没有其他原因,通常应该这样做,并且即使您有这样的理由,您也可以用这种方式轻松地进行模拟),则包装的函数始终可用作__wrapped__
。因此,您可以编写一个decorator,它可以有条件地轻松删除最外层的装饰:同样,如果你想动态地做这件事,你可能会动态地装饰。因此,一个更简单的解决方案是跳过您不想要的装饰器,在应用它们之前将它们从
decos
iterable中删除。在相关问题 更多 >
编程相关推荐