Python文档中__init_subclass__示例的Mypy报错解决问询
解决mypy无法识别__init_subclass__添加的类属性问题
针对你遇到的mypy报错问题,有几种可行的解决方式:
方法一:在父类中添加类属性类型注解
在Philosopher类中显式声明default_name为类级别的类型注解,让mypy明确知道所有子类都会拥有这个属性:
from typing import ClassVar class Philosopher: default_name: ClassVar[str] # 声明类属性类型 def __init_subclass__(cls, /, default_name: str, **kwargs): super().__init_subclass__(**kwargs) cls.default_name = default_name class AustralianPhilosopher(Philosopher, default_name="Bruce"): pass # 此时mypy会正确识别AustralianPhilosopher.default_name print(AustralianPhilosopher.default_name)
方法二:使用typing.Protocol定义子类契约
如果希望更严格地约束子类必须包含default_name属性,可以定义一个协议,让子类遵循该契约:
from typing import Protocol, ClassVar class HasDefaultName(Protocol): default_name: ClassVar[str] class Philosopher: def __init_subclass__(cls, /, default_name: str, **kwargs): super().__init_subclass__(**kwargs) cls.default_name = default_name class AustralianPhilosopher(Philosopher, default_name="Bruce"): default_name: ClassVar[str] # 显式实现协议要求的属性 # 类型检查时,mypy会确认子类符合协议 def greet_philosopher(philosopher_cls: type[HasDefaultName]) -> str: return f"Hello, {philosopher_cls.default_name}!" print(greet_philosopher(AustralianPhilosopher))
方法三:使用mypy的# type: ignore临时忽略(不推荐)
如果只是临时绕过检查,可以在访问属性的地方添加忽略注释,但这会丢失类型检查的优势,仅建议在特殊场景下使用:
class Philosopher: def __init_subclass__(cls, /, default_name: str, **kwargs): super().__init_subclass__(**kwargs) cls.default_name = default_name class AustralianPhilosopher(Philosopher, default_name="Bruce"): pass # 添加忽略注释 print(AustralianPhilosopher.default_name) # type: ignore
最推荐方法一,它既简洁又能让mypy准确识别类属性的存在,符合类型检查的最佳实践。
内容的提问来源于stack exchange,提问作者Some Guy
相关产品推荐
相关产品推荐

