2010-09-17 59 views
2

我知道在Python中檢查類型是不好的,你應該永遠不要這樣做。但我似乎無法找到這方面的劣勢。這是檢查Python中的類型的一個很好的理由嗎?

class O(object):   
    def __init__(self, name): 
     '''Can only be called in derived classes.''' 
     if type(self) is O: 
      message = "%(class)s cannot be instantiated, it must be derived." 
      raise TypeError, message % { "class" : O } 
     self.name = name 

    def fn(self): 
     '''Must be populated in derived classes.''' 
     raise NotImplementedError 

現在,如果有人試圖實例O,我從未想過一個類實例化,他們馬上就知道。

這仍然是不好的形式?

+2

爲什麼你不想要這個子類? – aaronasterling 2010-09-17 08:51:35

回答

5

請看Abstract Base Classes,因爲如果這是您真正想要做的事情,它們將對子類的實例化方式提供更精細的控制。

一切的一切,因爲你不會阻止從通過任何想你的代碼,但我仍然不認爲這是Python的,這可能是一個有效的使用。你正在告訴不能實例化你的類。如果我想要?

使用ABC的,它看起來像:

import abc 

class O(object): 
    __metaclass__ = abc.ABCMeta  
    def __init__(self, name): 
     self.name = name 

    @abc.abstractmethod 
    def fn(self): 
     pass 

這對fn方法不破壞超的優勢。正如你對raise NotImplementedError所做的那樣,你已經超越了多重繼承。如果一個類派生自子類O的兩個類並且都調用super(因爲它們應該允許多重繼承),那麼它將創建您引發的異常。

所以現在,你不只是告訴我,我不能實例化你的類,你告訴我,當從你的類繼承時,我不能使用多重繼承。

+0

我編輯後更清楚地表明意圖。我經常這樣做,通過閱讀代碼或試圖在不理解的情況下使用它,這樣做的目的顯而易見。 – cory 2010-09-17 09:23:08

+0

@Cory,根據您的更新,您確實需要ABC。看到我的更新。 – aaronasterling 2010-09-17 09:48:39

+0

你的例子很棒,你引發了我對abc模塊的興趣。但是你忘記了__metaclass上的最後兩個下劃線 – cory 2010-09-17 15:42:28

5

不要檢查,我們都是在這裏的大人。只需添加註釋O不應直接實例化,無論是作爲註釋還是在文檔中。

這就好像有人打電話要求使用int作爲其參數的方法,而不是string。如果程序崩潰,他們搞砸了。否則,你將需要添加類型檢查幾乎所有東西。

1

你試圖用上面的代碼實現什麼?

在這種情況下,自我的類型爲O,並且總是會引發異常。

看這個片段瞭解它好一點

class O(object):   
    def __init__(self, name): 
     self.name = name  

o = O("X") 

print type(o) 
print isinstance(o, O) 
if type(o) is O: 
    print "Yes" 

這將輸出

<class '__main__.O'> 
True 
Yes 
+0

它不會引發異常,如果你繼承它是點 – aaronasterling 2010-09-17 08:39:26

+0

我的代碼阻止用O()創建O的任何實例,但是從O派生的任何類都將能夠實例化自己。 – cory 2010-09-17 08:40:47

+0

+1我完全不理解它。雖然很順利。 – pyfunc 2010-09-17 08:41:38

相關問題