这个问题建立在许多假设之上。如果一个假设是错误的,那么整个事情就会失败。我还是相对较新的Python,刚刚进入了好奇/探索阶段。
我的理解是Python不支持创建不能被子类化的类( final 类)。但是,在我看来,Python中的 bool 类不能被子类化。当考虑bool类的意图时,这是有道理的(因为bool只应该有两个值:true和false),我很满意。我想知道的是 这个类被标记为最终的。
所以我的问题是: Guido如何成功阻止bool的子类化?
>>> class TestClass(bool):
pass
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
class TestClass(bool):
TypeError: type 'bool' is not an acceptable base type
答案 0 :(得分:45)
您可以非常轻松地模拟Python 3.x中的相同效果:
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 C(metaclass=Final): pass
class D(C): pass
将提供以下输出:
Traceback (most recent call last):
File "C:\Temp\final.py", line 10, in <module>
class D(C): pass
File "C:\Temp\final.py", line 5, in __new__
raise TypeError("type '{0}' is not an acceptable base type".format(b.__name__))
TypeError: type 'C' is not an acceptable base type
答案 1 :(得分:13)
您只能通过C API执行此操作。清除类型对象tp_flags
的{{3}}位。
喜欢这样:Py_TPFLAGS_BASETYPE
(对http://svn.python.org/projects/python/trunk/Objects/boolobject.c设置了Py_TPFLAGS_BASETYPE
。)
答案 2 :(得分:1)
在Python 3.6中,您可以阻止子类化,而无需使用如下这样的元类:
class SomeBase:
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
if cls is not SomeBase:
raise TypeError("SomeBase does not support polymorphism. Use composition over inheritance.")
class Derived(SomeBase):
pass
答案 3 :(得分:1)
Final
和@final
类型现在在typing_extensions
中可用。
我写了一篇文章,涵盖了这种新类型的几乎所有部分:https://sobolevn.me/2018/07/real-python-contants
一些带有类的示例:
from typing_extensions import final
@final
class HRBusinessUnit(AbstractBusinessUnit):
def grant_permissions(self) -> None:
self.api.do_some_hr_stuff()
class SubHRBusinessUnit(HRBusinessUnit): # mypy will raise an error
def grant_permissions(self) -> None:
self.api.do_some_it_stuff()
并带有常量:
from typing_extensions import Final
DAYS_IN_A_WEEK: Final = 7
DAYS_IN_A_WEEK = 8 # mypy will raise an error
我们还有一个小的库,可以编写final
类,这些类也可以在运行时检查! https://github.com/wemake-services/final-class
from final_class import final
@final
class Example(object): # You won't be able to subclass it!
...
class Error(Example): # Raises `TypeError`
...
功能: