2012-03-17 70 views
2

我正在構建一個利用屬性鏈接的Python類。我試圖弄清楚是否有一種方法可以確定鏈的最終屬性何時被調用,並執行一些處理代碼。在調用最終的鏈接屬性之後,我想要處理收集的數據。我意識到可以在鏈的末尾顯式調用處理屬性,但如果可能的話,我想避免這種情況。鏈接方法後調用屬性

例如:

o = ObjectInstance() 
# Note that the attribute calling order is subjective 
o('data').method_a('other data').method_c('other_data') #o.process() is called here automatically 

--Update--

我找到了一個解決方法是具體到我的情況,但沒有回答的基本問題。

對於我的特殊情況,我打算用單個實例分別處理多個鏈。通過重寫我的類的__call__屬性,我可以檢查前一個鏈是否已經被處理,並作出相應的反應。我已經計劃擁有一個單獨的渲染方法---在處理完所有鏈之後也可以處理前一個鏈,所以它適用於我的特定場景。

類看起來是這樣的:

class Chainable: 

    current_chain_data = None 
    processed_chains = list() 


    def __call__(self, data): 
     if self.current_chain_data: 
      self.process() 

     #Some logic 
     self.current_chain_data = data 
     return self 


    def method_a(self, data): 
     #Some logic 
     self.current_chain_data = data 
     return self 

    def method_b(self, data): 
     #... 

    def process(self, data): 
     #do stuff 
     self.processed_chains.append(self.current_chain_data) 
     self.current_chain_data = None 

    def render(self): 
     if self.current_chain_data: 
      self.process() 

     for c in self.processed_chains: 
      output += c 
     return output 

,並使用類似:

​​3210
+1

「如果可能,我想盡量避免。」請不要。顯式比隱式更好。 – 2012-03-17 17:45:19

+0

我看到你來自哪裏,對於像我上面發佈的一個簡單示例,我完全同意。但是,對於我的用法,關鍵目標是(儘可能準確地)維護非Python腳本語言的熟悉語法。 – 2012-03-17 17:54:45

+0

我建議你的解決方案可能會混淆你的用戶,因爲它是不統一的。如果在調用'c'前有人在'c'上調用另一個方法會發生什麼?你的用戶會期待這種行爲嗎? – Marcin 2012-03-20 10:31:32

回答

1

有沒有辦法來識別 「最後」 的呼叫,因爲一個 「產業鏈」不是一種語言結構,而是一種統一的語法結合自己的(良好的)從非功能性方法返回相同對象的做法的結果。

的選項有:

  1. 有一個最後的通話過程中,你的建議(在許多方面乾淨的解決方案);
  2. 在每個階段執行處理(這可能會影響性能,也可能不會影響性能,具體取決於處理以及您的方法實際執行的操作);或
  3. 每個方法都定義了一個關鍵字參數,它允許您將其標記爲最終調用,以觸發處理。

我會建議選項1,除非選項2自然不會產生性能損失,如果沒有其他原因,它會引入最小複雜性,並且顯式通常優於隱式。

您的覆蓋__call__的解決方案有幾個缺點:它可能會混淆你的用戶,因爲它是不統一的;如果有人在致電c之前致電c上的另一種方法,這種行爲可能會讓他們感到驚訝(連鎖繼續);最後,你仍然需要最後一個render調用來關閉最後一個鏈,這將使這樣的代碼比必要的更脆弱。

+0

我認爲你的觀點都非常有效。我選擇了最終處理調用的路線(在這種情況下是一個渲染方法),它可以很好地工作(並且在語義上,我可能會添加),這個工程是爲這個項目構建的。我相信它不會讓用戶感到困惑,因爲該課程幾乎完全反映了該課程直接與之集成的非Python腳本語言的熟悉語法。謝謝! – 2012-03-20 14:30:16

+0

@CaseyKinsey酷!如果你想讓用戶使用python,你可能還想提供一個普通的界面,以解決他們習慣的問題(當然,這可能根本不適用於你的情況)。 – Marcin 2012-03-20 14:32:50

0
class DataObject: 

     def __init__(self, data): 

       self.data = data 


     def method_a(self, data): 

       self.data += data 

       return self 


     def method_c(self, data): 

       self.data += data 

       return self 

     def process(self): 

       print self.data 

if __name__ == "__main__": 

     o = DataObject('data') 
     o.method_a('other data').method_c('other_data').process() 
+0

如果有明確的呼叫次序,這將起作用,但正如我在我的問題中指出的那樣,這是主觀的。 'method_c'可能在'method_a'之前被調用。 – 2012-03-17 17:29:17

+0

@CaseyKinsey在這種情況下,您可能必須顯式調用.process(),我已編輯以反映這一點。 – John 2012-03-17 17:38:33

+0

是的,我在我的問題中指出,我可能必須解決這個問題。我確實找到了一個解決方案,用於解決上面發佈的特定情況,但我仍然很好奇,是否有Pythonic方式以更通用的方式處理它,但我並不知道。 – 2012-03-17 17:46:19