将适配器类传入端口触发mypy类型错误,如何修正?
问题分析与修正
你的问题核心是类型标注与实际传入对象不匹配,同时对Protocol的使用场景存在误解:
错误原因
"SomePort" not callable:你给get_instance的参数port标注为SomePort,这表示它应该是SomePort的实例,但实例默认不可被调用(除非定义了__call__方法),而你在函数里执行了port(),因此mypy报错。- 类型不兼容:你传入的
SomeAdapter是类本身(类型为Type[SomeAdapter]),但参数标注要求的是SomePort实例,两者类型不匹配,导致第二个错误。
修正方案
你需要明确:get_instance需要接收的是一个可调用对象(这里是类的构造器),调用后能返回符合SomePort协议的实例。因此要把参数类型改为Callable[[], SomePort],表示“无参、返回SomePort实例的可调用对象”。
修正后的代码:
from typing import Protocol, Callable class SomePort(Protocol): def caller(self) -> None: raise NotImplementedError class SomeAdapter: def caller(self) -> None: print("Called") class SomeController: @staticmethod def get_instance(port: Callable[[], SomePort]) -> SomePort: return port() instance = SomeController.get_instance(port=SomeAdapter) instance.caller()
可选优化:显式继承Protocol
如果想让类型关系更清晰,可以让SomeAdapter显式继承SomePort(这不是必须的,因为Protocol是结构子类型,只要方法签名匹配就会被认可):
class SomeAdapter(SomePort): def caller(self) -> None: print("Called")
这样mypy会更明确地识别SomeAdapter符合SomePort协议,同时不影响代码运行逻辑。
内容的提问来源于stack exchange,提问作者Steinn Hauser Magnússon
相关产品推荐
相关产品推荐

