【问题标题】:Apply a single decorator to multiple functions将单个装饰器应用于多个函数
【发布时间】:2015-08-14 08:10:24
【问题描述】:

我已经搜索过这个,但我看到的结果正好相反:将多个装饰器应用于单个函数。

我想简化这个模式。有没有办法将此单个装饰器应用于多个功能?如果没有,我该如何重写上面的内容以减少重复?

from mock import patch

@patch('somelongmodulename.somelongmodulefunction')
def test_a(patched):
    pass  # test one behavior using the above function

@patch('somelongmodulename.somelongmodulefunction')
def test_b(patched):
    pass  # test another behavior

@patch('somelongmodulename.somelongmodulefunction')
def test_c(patched):
    pass  # test a third behavior
from mock import patch

patched_name = 'somelongmodulename.somelongmodulefunction'

@patch(patched_name)
def test_a(patched):
    pass  # test one behavior using the above function

@patch(patched_name)
def test_b(patched):
    pass  # test another behavior

@patch(patched_name)
def test_c(patched):
    pass  # test a third behavior

【问题讨论】:

  • 有什么问题?您的示例代码应该可以正常工作,并且尽可能地像 Python 一样。除了将装饰器应用于三个函数之外,没有其他“更简单”的方法可以将装饰器应用于三个函数。
  • 我不同意 - 有一种更简单的方法。 @justhecuke 提出了一个原则上可行的答案,我测试了一个可行的变体。您可以从 globals() 获取所需的函数名称列表,并将修饰的函数分配回它们。如果您有很长的单元测试列表并且您想对每个测试应用相同的模拟,这可能会很有意义。

标签: python decorator


【解决方案1】:

如果您只想进行一次“长”函数调用并用结果装饰所有三个函数,只需执行此操作即可。

my_patch = patch('somelongmodulename.somelongmodulefunction')

@my_patch
def test_a(patched):
    pass

@my_patch
def test_b(patched):
    pass

【讨论】:

    【解决方案2】:

    如果你想花哨,可以修改globals()。下面的总体思路应该可行。

    test_pattern = re.compile(r'test_\w+')
    test_names = [name for name in globals().keys() if test_pattern.match(name)]
    for name in test_names:
      globals()[name] = decorate(globals()[name])
    

    【讨论】:

      猜你喜欢
      • 2020-11-22
      • 2015-02-01
      • 2014-11-07
      • 2020-10-21
      • 2019-11-05
      • 1970-01-01
      • 2017-01-25
      • 1970-01-01
      相关资源
      最近更新 更多