2013-04-17 53 views
7

我碰到在python docs以下:python如何防止類被子類化?

布爾([X])

一個值轉換爲一個布爾值,使用標準的真理測試程序。如果x爲假或省略,則返回False;否則它 返回True。 bool也是一個類,它是int的一個子類。 類 布爾不能被進一步子類。其唯一的實例是False,並且 是真的。

我從來沒有在我的生活要繼承bool,但是自然我馬上試了一下,果然:

>>> class Bool(bool): 
    pass 

Traceback (most recent call last): 
    File "<pyshell#2>", line 1, in <module> 
    class Bool(bool): 
TypeError: Error when calling the metaclass bases 
    type 'bool' is not an acceptable base type 

所以,問題:如何做?我可以將同樣的技術(或者不同的),以紀念我自己的類作爲final,即,以防止它們被子類?

+1

爲什麼你不希望繼承'bool'?你可以創建'10'子類來表示每個可能的布爾狀態。 – jamylak

+0

感謝@Martijn,這看起來像一個密切相關的問題。它在我的SO搜索過程中沒有出現(我應該考慮在搜索條件中添加「final」)。 – alexis

回答

13

bool類型是在C中定義,並且其tp_flags槽故意不包括Py_TPFLAGS_BASETYPE flag

C型需要,以紀念自己明確作爲子類化。

爲自定義Python類做到這一點,使用元類:

class Final(type): 
    def __new__(cls, name, bases, classdict): 
     for b in bases: 
      if isinstance(b, Final): 
       raise TypeError("type '{0}' is not an acceptable base type".format(b.__name__)) 
     return type.__new__(cls, name, bases, dict(classdict)) 

class Foo: 
    __metaclass__ = Final 

class Bar(Foo): 
    pass 

給出:

>>> class Bar(Foo): 
...  pass 
... 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 5, in __new__ 
TypeError: type 'Foo' is not an acceptable base type 
+0

謝謝,涵蓋它! – alexis

+0

在進一步的思考,我有一個問題:是否有任何目的的檢查'isinstance(B,決賽)'?我的意思是,這個'__new__'將只通過從'Final'繼承的類調用,那麼爲什麼不只是提高立即如果'CLS!=「Final''? – alexis

+0

@alexis:是的,因爲您需要命名您試圖從哪個基類繼承。 'Bar'不繼承'Final',它的子類'Foo',這就是爲什麼'isinstance(B,決賽)'測試返回TRUE該類。如果有更多的基類使用,你想告訴最終用戶這些基地的哪一個是不可繼承的。 –