2008-09-22 32 views
4

我有一些Python代碼根據來自和iCalendar文件的解析VEvent對象創建一個Calendar對象。哪個更pythonic,作爲模塊中的函數的工廠,還是作爲它創建的類的方法?

日曆對象只是有一個方法,在事件被解析時添加。

現在我想創建一個工廠函數,用於從文件對象,路徑或URL創建日曆。

我一直在使用iCalendar python module,它實現了一個工廠函數作爲一個類的方法直接在類,它返回的一個實例:

cal = icalendar.Calendar.from_string(data) 

從一點點我知道Java中,這是一個Java代碼中的常見模式,儘管我似乎發現更多的引用工廠方法是在一個不同的類上,而不是你真正想實例化實例的類。

問題是,這是否也被認爲是Pythonic?或者僅僅是將工廠功能創建爲模塊級別的方法,會被認爲是更加pythonic?

回答

6

這是pythonic不去思考某些模式中的深奧差異,你在某處閱讀,現在想要在任何地方使用,如工廠模式。

大多數時候你會認爲@staticmethod是一個解決方案,它可能更好地使用模塊函數,除非你在一個模塊中填充多個類,並且每個模塊都有相同接口的不同實現,那麼它會更好使用@staticmethod

通過@staticmethod或模塊函數創建實例的最終天氣幾乎沒有什麼區別。

我可能會使用類的初始值設定項(__init__),因爲python中更爲接受的「模式」之一是類的工廠是類初始化。

+0

的Pythonista說,「muuuuu」 – 2008-09-22 16:07:42

2

恕我直言,模塊級別的方法是一個更清潔的解決方案。它隱藏在Python模塊系統的後面,它爲它提供了一個唯一的名稱空間前綴,這是「工廠模式」通常使用的。

11

[備註。將「日曆」分爲一系列事件要非常謹慎,而「事件」 - 日曆上的單個事件。在你的問題,似乎可能會有一些混淆。]

工廠設計模式有很多變化。

  1. 一個獨立的便利功能(例如,calendarMaker(數據))

  2. 一個單獨的類(例如,CalendarParser)它建立您的目標類(日曆)。

  3. 一個類級方法(例如Calendar.from_string)方法。

這些有不同的目的。所有是Pythonic,問題是「你是什麼意思是?」和「什麼可能改變?」意義就是一切;改變很重要。

便利功能是Pythonic。像Java這樣的語言不能有自由浮動的功能;你必須在課堂中包裝一個孤獨的功能。 Python允許你在沒有類的開銷的情況下擁有一個孤獨的函數。當您的構造函數沒有狀態更改或備用策略或任何先前操作的內存時,函數是相關的。

有時候人們會定義一個類,然後提供一個便利函數,它使得類的實例,爲狀態和策略以及任何其他配置設置常用參數,然後調用該類的單個相關方法。這給你帶來了課堂的有狀態和獨立功能的靈活性。

使用了類級方法模式,但它有侷限性。其一,它不得不依賴於課堂級別的變量。由於這些可能會造成混淆,因此當您需要添加功能(如有狀態或替代策略)時,作爲靜態方法的複雜構造函數會遇到問題。請確保您永遠不會擴展靜態方法。

二,它或多或少與其他類方法和屬性無關。這種from_string只是Calendar對象的許多備選編碼之一。你可能有一個from_xml,from_JSON,from_YAML等等。這與日曆的內容或它的功能沒有任何關係。這些方法都是關於日曆如何編碼進行傳輸的。

您會在成熟的Python庫中看到的是,工廠與創建的東西是分開的。編碼(如字符串,XML,JSON,YAML)受到很多或多或少的隨機變化。然而,基本的東西很少會改變。

分開這兩個問題。保持編碼和表示儘可能遠離狀態和行爲。

0

靜態方法很少有價值,但類方法可能有用。這取決於你想要什麼類和工廠功能實際上做。

模塊中的工廠函數總是會創建'正確'類型的實例(其中'正確'在你的案例中是'日曆'類,但是你也可以使它依賴於它的內容正在創建實例。)

如果您希望使其不依賴於數據,而是依賴於您所調用的類,請使用classmethod。 classmethod就像一個靜態方法,你可以在類上調用它,而不需要實例,但它接收到它作爲第一個參數被調用的類。這允許您實際創建類的實例,該實例可能是原始類的子類。類方法的一個例子是dict.fromkeys(),它從一個鍵和一個值列表中創建一個字典(默認爲None)。因爲它是一個類方法,所以當你爲字典子類時,完全免費獲得'fromkeys'方法。下面是一個如何能寫dict.fromkeys()的例子自己:

class dict_with_fromkeys(dict): 
    @classmethod 
    def fromkeys(cls, keys, value=None): 
     self = cls() 
     for key in keys: 
      self[key] = value 
     return self 
相關問題