将python装饰器应用于类中的方法

时间:2010-02-10 14:51:11

标签: python decorator

我对方法 test_1

应用了装饰器@login_testuser
class TestCase(object):
    @login_testuser
    def test_1(self):
        print "test_1()"

有没有办法可以在前缀为“test _”的类的每个方法上应用@login_testuser

换句话说,装饰器将适用于下面的 test_1 test_2 方法,但不适用于 setUp

class TestCase(object):
    def setUp(self):
        pass

    def test_1(self):
        print "test_1()"

    def test_2(self):
        print "test_2()"

4 个答案:

答案 0 :(得分:20)

在Python 2.6中,class decorator绝对是可行的方法。例如,这是一个非常普遍的这类任务:

import inspect

def decallmethods(decorator, prefix='test_'):
  def dectheclass(cls):
    for name, m in inspect.getmembers(cls, inspect.ismethod):
      if name.startswith(prefix):
        setattr(cls, name, decorator(m))
    return cls
  return dectheclass

现在,只是

@decallmethods(login_testuser)
class TestCase(object):
    def setUp(self):
        pass

    def test_1(self):
        print "test_1()"

    def test_2(self):
        print "test_2()"

会得到你想要的东西。在Python 2.5或更糟的情况下,@decallmethods语法不适用于类装饰,但是在完全相同的代码中,您可以使用以下语句将其替换为结束后{1}}陈述:

class TestCase

答案 1 :(得分:3)

不确定。迭代类的所有属性。检查每个方法是否为方法,如果名称以“test_”开头。然后用装饰器返回的函数替换它

类似的东西:

from inspect import ismethod, getmembers
for name, obj in getmembers(TestCase, ismethod):
   if name.startswith("test_"):
       setattr(TestCase, name, login_testuser(obj))

答案 2 :(得分:3)

您确定将login_testuser的代码放入setUp会不会更好?这就是setUp的用途:它在每个测试方法之前运行。

答案 3 :(得分:0)

是的,你可以遍历班级的dir / __dict__或者有一个这样做的元类,确定属性是否以“test”开头。但是,与明确编写装饰器相比,这将创建更简单明了的代码。