Python3.x中的最后一个类Guido没有告诉我什么?

2024-06-16 17:37:30 发布

您现在位置:Python中文网/ 问答频道 /正文

这个问题建立在许多假设之上。如果一个假设是错误的,那么整个事情就完了。我对Python还比较陌生,刚刚进入好奇/探索阶段

据我所知,Python不支持创建不能子类化的类(finalclasses)。然而,在我看来,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

相关问题:Why I can't extend bool in Python?


Tags: infalsetruetype错误事情阶段意图
3条回答

您可以很容易地从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

您只能通过C API来实现这一点。清除类型对象的tp_flags^{}

例如,bool不能子类化(cpython-code on github):

PyTypeObject PyBool_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "bool",
    ...
    0,                                          /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT,                         /* tp_flags */
    ...
};

但是int可以(cpython-code on github):

PyTypeObject PyLong_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "int",                                      /* tp_name */
    ...
    0,                                          /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
        Py_TPFLAGS_LONG_SUBCLASS,               /* tp_flags */
    ...
};

因为Py_TPFLAGS_BASETYPE-位是在tp_flags中设置的

在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

在Python 3.8中,还应使用final装饰器来引发类型检查错误:

from typing import final


@final
class SomeBase:
    ...

类型检查由MyPy之类的程序完成,这是可选的

相关问题 更多 >