2011-12-08 35 views
1

如果對象依賴於未包含在Python中的模塊(如win32api,gstreamer,gui工具包等),並且該模塊中的類/函數/方法可能會失敗,那麼該對象應該做什麼?Python:如何處理無法正確初始化的類的方法調用?

下面是一個例子:

import guimodule # Just an example; could be anything 

class RandomWindow(object): 

    def __init__(self): 
     try: 
      self.dialog = guimodule.Dialog() # I might fail 
     except: guimodule.DialogError: 
      self.dialog = None # This can't be right 

    def update(self): 
     self.dialog.prepare() 
     self.dialog.paint() 
     self.dialog.update() 

    # ~30 more methods 

這個類僅是一個更大的程序的一個微小的(和不必要的,但有用的)部分。

假設我們有一個名爲guimodule的假想模塊,其類名爲Dialog,可能無法實例化。如果我們的RandomWindow類有說,操縱這個窗口的30個方法,檢查if self.dialog is not None將是一個痛苦,並且將在使用常用方法(例如上面的示例中的update方法)中執行時減慢程序速度。在NoneType上調用.paint()(當Dialog加載失敗時)將引發錯誤,並且使用所有原始方法和屬性製作虛擬類將是荒謬的。

如何修改我的班級以處理Dialog班級的失敗創建?

回答

3

而不是創建一個無效的對象,你應該允許在__init__中引發的異常傳播出去,以便以適當的方式處理錯誤。或者你可能提出了一個不同的例外。

又見Python: is it bad form to raise exceptions within __init__?

+0

爲什麼這會比內部處理錯誤更好/更簡單? –

+0

@DK,直接知道對象不能被使用,而不是在每次使用對象時都會失敗,這很簡單。 –

1

您可能會發現它有兩個子類是有用的;一個使用該模塊,另一個不使用該模塊。 「工廠」方法可以確定哪個子類是合適的,並返回該子類的實例。

通過子類化,您可以讓他們共享獨立於該模塊是否可用的代碼。

+0

這樣做的問題是,我會每次我修改原始修改虛擬/子類(這將是惱人的保持同步)。 –

0

我同意「檢查是否self.dialog不無會痛」,但我不同意,它會減慢的事情,因爲如果self.dialog存在這樣會更慢。所以忘記暫時的慢。所以一種處理方法是創建一個MockDialog,它在函數調用中不做任何事情,例如

class RandomWindow(object): 

    def __init__(self): 
     try: 
      self.dialog = guimodule.Dialog() # I might fail 
     except: guimodule.DialogError: 
      self.dialog = DummyDialog() # create a placeholder 

class DummyDialog(object): 
    # either list all methods or override __getattr__ to create a mock object 
0

製作假Dialog類不是因爲你可能的事情,如果你考慮使用蟒蛇__getattr__功能一樣荒謬。這下虛的實現將完全滿足您的需求:

class DummyDialog: 
    def __getattr__(self, name): 
    def fct(*args, **kwargs): 
     pass 
    return fct 
+0

如果有返回方法會怎麼樣? –

+0

你說得對,具有返回值的對話框方法不能像這樣被嘲笑。您可以在'DummyDialog'中單獨定義它們並返回任何虛擬值,或者您必須選擇一些完全不同的方法,如Aaron提出的涉及子類化的方法。 – gecco

相關問題