2010-03-10 99 views
0

首先,我不知道這是否是正確的方法。我想寫一個將用於其他類的方法的裝飾器類。在運行該方法之前,我想檢查是否所有需要的類變量都已初始化。理想的情況是類似於這樣的:Decorator類來測試所需的類變量

class Test(object): 
    def __init__(self, f): 
     self.f = f 
     # some magic 

    def __call__(self): 
     self.f.magically_get_variable(required) 
     # do some checks and execute method or throw an exception 

class Data(object): 
    def __init__(self, a, b): 
     self.a = a 

    @test 
    def sum(self): 
     required('self.a', 'self.b') 
     return self.a + self.b 

如果這不是它應該做的方式,請告訴我如何正確地做到這一點。

回答

1

我會說裝飾者有點不適合在這裏檢查是否存在變量的目的。

想想你打算做什麼,如果沒有提供所需的變量:引發異常(它在你的評論)。

我想說(基於上面的代碼):

def sum(self): 
    return self.a + self.b 

而且讓它失敗如果沒有提供self.a或self.b(這將引發NameError異常,可以趕上如果你喜歡,你可以,如果你想提高自己當時)

+0

+1:'NameError'告訴你比任何裝飾更。它內置。它始終有效。 – 2010-03-10 20:24:48

0

如果你堅持要檢查裝飾方法的身體開始之前,以下是一個合理的方式來做到這一點...:

import functools 

class test(object): 
    def __init__(self, requiredvars): 
     self.reqs = requiredvars.split() 

    def __call__(self, f): 
     @functools.wraps(f) 
     def wrapper(wself, *a, **k): 
      missing = set() 
      for v in self.reqs: 
      if not hasattr(wself, v): 
       missing.add(v) 
      if missing: 
      msg = 'missing fields: %s' % ','.join(sorted(missing)) 
      raise valueerror, msg 
      return f(wself, *a, **k) 
     return wrapper 

class data(object): 
    def __init__(self, a, b): 
     self.a = a 

    @test('a b') 
    def sum(self): 
     return self.a + self.b 

d = data(23, 42) 
d.sum() 

這發出,你顯然希望,

Traceback (most recent call last): 
    File "rev.py", line 29, in <module> 
    d.sum() 
    File "rev.py", line 16, in wrapper 
    raise ValueError, msg 
ValueError: Missing fields: b