通过装饰器注入类属性

时间:2019-03-17 17:33:03

标签: python django pycharm decorator testcase

我有一堆Django TestCases,它们使用setUp方法来初始化在众多测试中使用的某些属性,这些属性的构造方式和相互依赖是我想从测试用例中移出的逻辑,重用

def setUp(self):
    self.property_1 = ##some logic
    ...

我想将它们重写为一些方便的包装,可以通过简单的继承或装饰器将其注入到类中,例如

@with_property_1(x=1, y=2)
def setUp(self):
    ...


def with_property_1(**model_kwargs):
    def wrapper(f):
        def wrapped(*args, **kwargs):
            self = args[0]
            self.property_1 = ## logic
            f(*args, **kwargs)
        return wrapped
    return wrapper

但是麻烦的是PyCharm无法识别那些实例属性的存在,因为TestCase类内部没有任何东西可以设置它们。是我可以很好地实现这一目标的另一种方法,还是在装饰器存在的情况下哄骗PyCharm识别这些属性是合法的方法?

1 个答案:

答案 0 :(得分:0)

免责声明:未经测试。

这里的问题是Python不能仅仅神奇地将self放在装饰器的上下文中(在任何IDE中都无法使用)。您可能会忘记的是,self是您调用每个类方法时传递给它的参数之一。因此,它存在于您的*args中,您可以对其进行操作。

这是我的试用代码:

def with_property_1(**model_kwargs):
  def wrapper(f):
    def wrapped(*args, **kwargs):
      for key, value in model_kwargs.items():
        setattr(args[0], key, value)
      f(*args, **kwargs)
    return wrapped
  return wrapper

说明:

  1. 遍历**model_kwargs中的每个键/值。

  2. 使用args[0]修改self,它应该是setattr变量,并使用提供的kwarg。

  3. 使用更新后的self变量正常调用该函数。