2009-07-06 23 views
4

我會直奔例如不執行的方法:裝飾,以紀念被超過一次,即使所謂的幾次

class Foo: 
    @execonce 
    def initialize(self): 
    print 'Called' 

>>> f1 = Foo() 
>>> f1.initialize() 
Called 
>>> f1.initialize() 
>>> f2 = Foo() 
>>> f2.initialize() 
Called 
>>> f2.initialize() 
>>> 

我試圖定義execonce,但不能寫一個與方法的工作原理。

PS:在__init__initialize我不能定義代碼有被稱爲初始化對象後的某個時間。 CF - cmdln issue 13

+1

橫向評論:我建議你不要忽略第二個電話。相反,你應該提出異常。如果一個調用者進行了兩次初始化,出現了錯誤,您應該報告而不是默默地忽略它。當然,我不知道你的具體問題。 – 2009-07-06 20:34:51

+0

Stefano,我同意..這對我來說也感覺很奇怪。基本上,測試用例依次調用這些子命令方法(例如:'svn commit'),如下所示:command.do_commit和command.do_update。每個這些子命令都必須調用`initialize`方法(參見cmdln issue 13)。我不想提出異常。爲什麼調用者(測試用例)需要知道這樣的內部細節? – 2009-07-06 20:37:30

回答

6
import functools 

def execonce(f): 

    @functools.wraps(f) 
    def donothing(*a, **k): 
     pass 

    @functools.wraps(f) 
    def doit(self, *a, **k): 
     try: 
      return f(self, *a, **k) 
     finally: 
      setattr(self, f.__name__, donothing) 

    return doit 
+0

我得到`TypeError:donothing()至少需要1個參數(0給出)` – 2009-07-06 20:28:39

+0

好吧,通過從`donothing`方法中刪除`self`參數..我能夠完成這項工作。 – 2009-07-06 20:35:11

0

你可以做這樣的事情:

class Foo: 
    def __init__(self): 
    self.initialize_called = False 
    def initialize(self): 
    if self.initalize_called: 
     return 
    self.initialize_called = True 
    print 'Called' 

這很簡單,易於閱讀。在__init__函數中還需要另一個實例變量和一些代碼,但它會滿足您的要求。

0

嘗試與此類似

def foo(): 
    try: 
      foo.called 
    except: 
      print "called" 
      foo.called = True 

方法的東西,函數是對象。你可以在它們上添加方法和屬性。這對你的情況很有用。如果你想裝飾器,只需要裝飾器分配方法,但首先檢查標誌。如果找到該標誌,則返回一個空方法並隨後執行。