2013-04-17 8 views
7

stieß ich auf die folgenden in der python docs:Wie verhindert Python, dass eine Klasse unterklassifiziert wird?

bool ([x])

Wert auf einen Boolean konvertieren, die Standard Wahrheit Testverfahren verwendet wird. Wenn x falsch oder weggelassen ist, gibt dies Falsch zurück; andernfalls gibt True zurück. Bool ist auch eine Klasse, die eine Unterklasse von int ist. Klasse Bool kann nicht weiter unterklassifiziert werden. Die einzigen Instanzen sind False und True.

Ich habe noch nie in meinem Leben wollte bool, Unterklasse, aber es natürlich habe ich versucht sofort, und sicher genug:

>>> 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 

Also, die Frage: Wie wird das gemacht? Und kann ich die gleiche Technik (oder eine andere) anwenden, um meine eigenen Klassen als final zu markieren, d. H. Um zu verhindern, dass sie unterklassifiziert werden?

+1

Warum wollen Sie nicht 'bool' Unterklasse? Sie könnten '10' Unterklassen erstellen, um jeden möglichen booleschen Zustand darzustellen. – jamylak

+0

Dank @Martijn, das sieht aus wie eine eng verwandte Frage. Es kam nicht während meiner SO-Suche auf (ich hätte gedacht, dass ich "final" zu den Suchbegriffen hinzufügen würde). – alexis

Antwort

13

Der bool Typ ist in C definiert, und sein tp_flags Steckplatz enthält absichtlich nicht die Py_TPFLAGS_BASETYPE flag.

C-Typen müssen sich selbst markieren explizit als Unterklasse.

diese Klassen für benutzerdefinierte Python Verwenden Sie dazu eine Metaklasse:

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 

gibt:

>>> 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

Danke, das deckt es ab! – alexis

+0

Bei weiterem Nachdenken habe ich eine Frage: Gibt es irgendeinen Zweck für den Check 'isinstance (b, Final)'? Ich meine, dieses "__new__" wird immer nur von einer Klasse aufgerufen, die von "Final" erbt, also warum nicht einfach sofort erhöhen, wenn "cls! = 'Final"? – alexis

+0

@alexis: Ja, weil Sie die Basisklasse benennen müssen, von der Sie versucht haben zu erben. 'Bar' untergliedert nicht' Final', sondern Unterklassen 'Foo', weshalb der' isinstance (b, Final) '- Test für diese Klasse' True' zurückgibt. Wenn mehrere Basisklassen verwendet werden, möchten Sie dem Endbenutzer mitteilen, welche dieser Basen nicht vererbbar ist. –

Verwandte Themen