禁止向 Python 个子 class 添加新方法

Prohibit addition of new methods to a Python child class

我有两个 class 应该为两个独立的库实现相同的测试用例(我们称它们为 LibALibB).到目前为止,我定义了要在抽象基础 class 中实现的测试方法,这确保两个测试 classes 都实现了所有需要的测试:

from abc import ABC, abstractmethod

class MyTests(ABC):
    @abstractmethod
    def test_foo(self):
        pass

class TestsA(MyTests):
    def test_foo(self):
        pass

class TestsB(MyTests):
    def test_foo(self):
        pass

这按预期工作,但仍然可能发生的是有人在 LibB 上工作时不小心将 test_bar() 方法添加到 TestB 而不是基础class。 TestA class 中缺失的 test_bar() 在这种情况下将不会被注意到。

有没有办法禁止向(抽象)基添加新方法class? objective 是强制在基础 class 中添加新方法,从而强制在所有派生的 classes 中实现新方法。

是的。它可以通过 metaclass 完成,或者从 Python 3.6 开始,检查 baseclass.

__init_subclass__

__init_sublass__ 是每次实例化 subclass 时由语言调用的特殊方法。因此它可以检查新的 class 是否有任何 superclasses 中不存在的方法,并在声明 subclass 时引发 TypeError。 (__init_subclass__ 自动转换为 class 方法)

class Base(ABC):
    ...
    def __init_subclass__(cls, *args, **kw):
        super().__init_subclass__(*args, **kw)
        # By inspecting `cls.__dict__` we pick all methods declared directly on the class
        for name, attr in cls.__dict__.items():
            attr = getattr(cls, name)
            if not callable(attr):
                continue
            for superclass in cls.__mro__[1:]:
                if name in dir(superclass):
                    break
            else:
                # method not found in superclasses:
                raise TypeError(f"Method {name} defined in {cls.__name__}  does not exist in superclasses")


请注意,与未实现的抽象方法引发的类型错误不同,此错误是在 class 声明时引发的,而不是 class 实例化时引发的。如果需要后者,则必须使用 metaclass 并将检查移至其 __call__ 方法 - 然而这会使事情复杂化,就好像在中间 class 中创建一个方法一样,从未实例化,当该方法在叶 subclass 中可用时,它不会引发。我猜你需要的是上面的代码。