Python协议不兼容警告

1 投票
1 回答
70 浏览
提问于 2025-04-14 15:46

我想要给我的纯混入类(MyMixin)加个提示,说明它希望父类里有一个叫做 get_context_data 的方法。

class HasViewProtocol(Protocol):
    kwargs: dict

    @abstractmethod
    def get_context_data(self, **kwargs) -> dict:
        pass


class MyMixin(HasViewProtocol):

    def get_context_data(self, **kwargs) -> dict:
        return super().get_context_data(**kwargs) | {
            "extra_data": "bla"
        }

这里是Pycharm的检查结果:

type of 'get_context_data' is incompatible with 'HasViewProtocol`
  • 使用协议(protocols)来标注我对父类的期望是否合适?
  • 为什么 get_context_dataHasViewProtocol 不兼容?

1 个回答

2

根据定义,抽象方法是没有具体实现的,直接调用这样的一个方法通常意味着代码有问题。但是在 MyMixinget_context_data() 方法中,你正好在做这样的事情。

class MyMixin(HasViewProtocol):
    def get_context_data(self, **kwargs) -> dict:
        return super().get_context_data(**kwargs) | {
           ....

你试图调用父类的抽象方法,所以我知道的所有代码检查工具都会把这个标记为错误。没错,我明白 MyMixin 是为了和那些已经实现了 get_context_data() 方法的类一起使用的,但在这个时候,代码检查工具并不知道这一点。而且不仅仅是 PyCharm,其他的代码检查工具也会有类似的反馈。比如,mypy 会报告:

错误:通过 super() 调用 "HasViewProtocol" 的抽象方法 "get_context_data" 的实现是危险的 [safe-super]

实际上,即使你去掉了装饰器,mypy 也会因为只有 pass 的实现而抱怨。

至于 PyCharm 提示的 get_context_data 的类型与 "HasViewProtocol" 不兼容的警告,这很可能与它如何理解代码有关。但在我看来,这个提示本身并不太对,也不太符合上下文,所以我建议你把这个问题反馈给 JetBrains,可以通过 PyCharm 的 bug 跟踪器 来报告。

撰写回答