2013-04-17 54 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该类。如果有更多的基类使用,你想告诉最终用户这些基地的哪一个是不可继承的。 –