哪些类不能被子类化?

关于哪些内置的和标准的库类是不可子类化的(“ final”) ,有什么规则吗?

至于 Python 3.3,这里有一些例子:

  • bool
  • function
  • operator.itemgetter
  • slice

我发现了一个 有个问题,它处理 C 和纯 Python 中“ final”类的实现。

我想知道是什么原因可以解释为什么一个类被选为“最终”摆在首位。

9636 次浏览

在 Python 中使用“ final”类似乎有两个原因。

1. 违反类不变式

跟随单例模式的类有一个不变量,即有一个有限的(预先确定的)数量。子类中任何违反此不变式的行为都将与类的意图不一致,并且不能正常工作。例子:

  • bool: TrueFalse; 参见 圭多的评论
  • NoneType: None
  • NotImplementedType: NotImplemented
  • ellipsis: Ellipsis

除了这类单例模式,可能还有其他案例,但我不知道有这样的案例。

2. 没有有说服力的用例

用 C 实现的类需要额外的工作来允许子类化(至少在 CPython 中)。在没有令人信服的用例的情况下进行这样的工作不是很有吸引力,因此志愿者不太可能站出来。例子:

注一:

我最初认为存在有效的用例,但是对 functionoperator.itemgetter的子类化兴趣不足。感谢@agf 指出提供的 给你给你用例并不具有说服力(请参见对问题的@agf 评论)。

注二:

我担心的是,另一个 Python 实现可能会意外地允许对 CPython 中的 final 类进行子类化。这可能导致不可移植的代码(用例可能很弱,但是如果 Python 支持的话,仍然可能有人编写子类 function的代码)。可以通过在 Python 文档中标记所有不能被子类化的内置和标准库类,并要求所有实现在这方面遵循 CPython 行为来解决这个问题。

注三:

CPython 在以上所有情况下产生的消息是:

TypeError: type 'bool' is not an acceptable base type

这是相当神秘的,因为无数的问题,这个主题显示。我将提交一个建议,在文档中添加一个段落来解释最终类,甚至可能将错误消息更改为:

TypeError: type 'bool' is final (non-extensible)

如果我们检查内置程序(不包括错误、 dunder 方法、警告; 如果需要也可以包括它们)

import keyword, re
x = sorted([i for i in list(keyword.__builtins__) if not re.search('.*Error|Warning|__', i)], key=len)

然后逃跑,

l1 = []
l2 = []
for i in x:
try:
A = type('A', (eval(i),), {})
l1.append(i)
except TypeError:
l2.append(i)

那么,

l1

给予,

['int', 'map', 'set', 'str', 'zip', 'dict', 'list', 'type', 'bytes', 'float',
'super', 'tuple', 'filter', 'object', 'complex', 'property', 'reversed',
'bytearray', 'enumerate', 'frozenset', 'Exception', 'SystemExit',
'classmethod', 'staticmethod', 'BaseException', 'StopIteration',
'GeneratorExit', 'KeyboardInterrupt', 'StopAsyncIteration']

同时,

l2

给予,

['id', 'abs', 'all', 'any', 'bin', 'chr', 'dir', 'hex', 'len', 'max', 'min',
'oct', 'ord', 'pow', 'sum', 'eval', 'exec', 'hash', 'iter', 'next', 'repr',
'vars', 'None', 'True', 'bool', 'open', 'help', 'ascii', 'input', 'print',
'round', 'False', 'range', 'slice', 'divmod', 'format', 'locals', 'sorted',
'compile', 'delattr', 'getattr', 'globals', 'hasattr', 'setattr', 'credits',
'license', 'display', 'runfile', 'dreload', 'callable', 'Ellipsis', 'execfile',
'copyright', 'breakpoint', 'isinstance', 'issubclass', 'memoryview',
'get_ipython', 'NotImplemented']

列表 l1包含可以作为基类的内建函数。