Здається, що є дві причини для того, щоб клас був "остаточним" у Python.
1. Порушення класової інваріанти
Класи, які слідують шаблону Синглтона, мають інваріант щодо обмеженої (заздалегідь визначеної) кількості випадків. Будь-яке порушення цього інваріанта в підкласі буде суперечити наміру класу і не працюватиме належним чином. Приклади:
bool
: True
, False
; див . коментарі Гвідо
NoneType
: None
NotImplementedType
: NotImplemented
ellipsis
: Ellipsis
У цій категорії можуть бути випадки, крім шаблону Сінглтона, але я не знаю жодного.
2. Немає переконливого випадку використання
Клас, реалізований на мові C, вимагає додаткової роботи, щоб дозволити підкласифікацію (принаймні в CPython). Робити таку роботу без переконливого випадку не надто привабливо, тому волонтери рідше виступають. Приклади:
Примітка 1:
Спочатку я думав, що існували обґрунтовані випадки використання, але просто недостатній інтерес для підкласифікації function
та operator.itemgetter
. Дякую @agf за те, що він зазначив, що запропоновані тут і тут випадки використання не є переконливими (див. Коментарі @agf до питання).
Примітка 2:
Мене турбує те, що інша реалізація Python може випадково дозволити підкласувати клас, який є остаточним у CPython. Це може призвести до непереносного коду (варіант використання може бути слабким, але хтось може все-таки написати код, що підкласи, function
якщо їхній Python це підтримує). Це можна вирішити, позначивши в документації Python всі вбудовані та стандартні класи бібліотеки, які не можна підкласифікувати, та вимагаючи, щоб усі реалізації відповідали поведінці CPython у цьому відношенні.
Примітка 3:
Повідомлення, яке видає CPython у всіх вищезазначених випадках:
TypeError: type 'bool' is not an acceptable base type
Це досить загадково, як свідчать численні запитання на цю тему. Я подаю пропозицію додати абзац до документації, що пояснює підсумкові класи, і, можливо, навіть змінити повідомлення про помилку на:
TypeError: type 'bool' is final (non-extensible)
NoneType
є ще одним прикладом.