Ответ 1
Кажется, есть две причины, чтобы класс был "окончательным" в Python.
1. Нарушение инвариантности класса
Классы, которые следуют шаблону Singleton, имеют инвариант, что существует ограниченное (предварительно определенное) количество экземпляров. Любое нарушение этого инварианта в подклассе будет несовместимо с умыслом класса и не будет работать корректно. Примеры:
-
bool
:True
,False
; см. комментарии Guido -
NoneType
:None
-
NotImplementedType
:NotImplemented
-
ellipsis
:ellipsis
В этой категории могут быть случаи, отличные от шаблона Singleton, но я не знаю о них.
2. Нет убедительного случая использования
Класс, реализованный на C, требует дополнительной работы, чтобы разрешить подкласс (по крайней мере, в CPython). Выполнение такой работы без убедительного варианта использования не очень привлекательно, поэтому добровольцы с меньшей вероятностью выходят вперед. Примеры:
-
function
; см. Сообщение Тима Петерса
Примечание 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)