Gibt es eine Regel darüber, welche integrierten und Standardbibliotheksklassen nicht in Unterklassen unterteilt werden können ("final")?
Ab Python 3.3 sind hier einige Beispiele:
bool
function
operator.itemgetter
slice
Ich habe eine Frage gefunden , die sich mit der Implementierung von "finalen" Klassen sowohl in C als auch in reinem Python befasst.
Ich würde gerne verstehen, welche Gründe erklären können, warum eine Klasse überhaupt als "endgültig" ausgewählt wird.
NoneType
ist ein weiteres Beispiel.function
und muss den Code jetzt umgestalten, um diese Vererbung zu vermeiden).NotImplementedType
(dhtype(NotImplemented)
) undellipsis
(dhtype(...)
) sind zwei weitere Beispiele. WieNone
, gibt es keinen Grund mehr als eine Instanz dieser Klassen zu haben, und wenn dies erlaubt wäre, würde es schwierig sein , für sie zu überprüfen (if x is None
würde müssenif isinstance(x, type(None))
). Ich nehme an, Sie könnten im Prinzip eine vollständige Liste erhalten, indem Sie in der Quelle nach dem Wert vontp_flags
in Typdefinitionen suchen .itemgetter
. und dieser Beitrag, warum Sie möglicherweise eine Unterklasse erstellen möchtenfunction
(dieser ist alt, daher gelten einige dieser Argumente möglicherweise nicht).Antworten:
Es scheint zwei Gründe dafür zu geben, dass eine Klasse in Python "endgültig" ist.
1. Verletzung der Klasseninvariante
Klassen, die dem Singleton-Muster folgen, haben die Invariante, dass es eine begrenzte (vorher festgelegte) Anzahl von Instanzen gibt. Jeder Verstoß gegen diese Invariante in einer Unterklasse widerspricht der Absicht der Klasse und würde nicht richtig funktionieren. Beispiele:
bool
:True
,False
; siehe Guidos KommentareNoneType
::None
NotImplementedType
::NotImplemented
ellipsis
::Ellipsis
Es kann andere Fälle als das Singleton-Muster in dieser Kategorie geben, aber mir sind keine bekannt.
2. Kein überzeugender Anwendungsfall
Eine in C implementierte Klasse erfordert zusätzliche Arbeit, um Unterklassen zu ermöglichen (zumindest in CPython). Solche Arbeiten ohne einen überzeugenden Anwendungsfall durchzuführen, ist nicht sehr attraktiv, daher ist es weniger wahrscheinlich, dass Freiwillige sich melden. Beispiele:
function
;; siehe Tim Peters 'BeitragAnmerkung 1:
Ich dachte ursprünglich, es gäbe gültige Anwendungsfälle, aber einfach unzureichendes Interesse an der Unterklasse von
function
undoperator.itemgetter
. Vielen Dank an @agf für den Hinweis, dass die hier und hier angebotenen Anwendungsfälle nicht überzeugend sind (siehe @agf-Kommentare zur Frage).Anmerkung 2:
Ich befürchte, dass eine andere Python-Implementierung versehentlich die Unterklasse einer Klasse zulässt, die in CPython endgültig ist. Dies kann zu nicht portierbarem Code führen (ein Anwendungsfall kann schwach sein, aber jemand schreibt möglicherweise immer noch Code, der in Unterklassen unterteilt ist,
function
wenn sein Python dies unterstützt). Dies kann behoben werden, indem in der Python-Dokumentation alle integrierten und Standardbibliotheksklassen markiert werden, die nicht in Unterklassen unterteilt werden können, und dass alle Implementierungen in dieser Hinsicht dem CPython-Verhalten folgen müssen.Notiz 3:
Die von CPython in allen oben genannten Fällen erzeugte Nachricht lautet:
TypeError: type 'bool' is not an acceptable base type
Es ist ziemlich kryptisch, wie zahlreiche Fragen zu diesem Thema zeigen. Ich werde einen Vorschlag einreichen, um der Dokumentation einen Absatz hinzuzufügen, in dem die letzten Klassen erläutert werden, und möglicherweise sogar die Fehlermeldung in Folgendes ändern:
TypeError: type 'bool' is final (non-extensible)
quelle
bool
einschließenunknown
:-P nur ein Scherzbool
, im Gegenteil, jeder einzelne boolesche Wert ist eine Art Qbit! eine, die zufällig beobachtet wird. Ich würde diesen Fall wahrscheinlich mit__subclasscheck__
und Freunden behandeln.slice
?LazyBool
)