使用__new__自定义Python类时遭遇Mypy报错求助
解决自定义
__new__方法时的Mypy类型错误 你在给抽象类和子类写自定义__new__方法时碰到了Mypy的类型检查报错对吧?先把你的简化代码和大概率会出现的报错信息列出来,咱们一步步解决:
你的代码
from abc import ABC, abstractproperty class A(ABC): def __new__(cls, x: int) -> 'A': return super().__new__(cls) @abstractproperty def log(self) -> None: pass class B(A): def __new__(cls, x: str) -> 'B': return super().__new__(cls, int(x)) def log(self) -> None: print('Hello World')
你遇到的Mypy报错
test.py:12: error: Argument 2 to "new" of "A" has incompatible type "int"; expected "str" [arg-type]
test.py:12: error: Return type "A" of "new" incompatible with return type "B" in supertype "A" [override]
问题分析
其实这里有两个核心问题:
__new__方法的签名不兼容:Mypy对方法重写的类型检查很严格,父类A的__new__接受int参数返回A实例,但子类B的__new__接受str参数返回B实例,这在类型系统里属于不兼容的重载。- 抽象成员用错了装饰器:你定义的
log是一个需要调用的方法,但用了@abstractproperty(这是用来标记抽象属性的,不需要加括号调用),应该换成@abstractmethod才对。
正确的解决办法
我给你两种方案,优先选第一种,因为它从根源上解决了类型问题:
方案1:规范类型标注+修正抽象成员
我们用TypeVar和Type来让Mypy正确识别子类__new__的返回类型,同时把装饰器修正过来:
from abc import ABC, abstractmethod from typing import TypeVar, Type # 定义一个绑定到A的类型变量,让Mypy知道返回的是子类实例 T = TypeVar('T', bound='A') class A(ABC): def __new__(cls: Type[T], x: int) -> T: # 用Type[T]标注cls,确保返回的是当前子类的实例 return super().__new__(cls) @abstractmethod def log(self) -> None: # 用abstractmethod标记抽象方法,符合定义 pass class B(A): def __new__(cls: Type['B'], x: str) -> 'B': # 明确标注当前类的类型和返回类型 return super().__new__(cls, int(x)) def log(self) -> None: print('Hello World')
这么改之后,Mypy就能正确理解:子类B的__new__虽然参数类型和父类不同,但调用父类时已经把str转成了int,符合父类的参数要求;同时返回的B实例也是父类返回类型A的子类型,完全兼容。
方案2:临时绕过检查(不推荐)
如果你只是想快速跳过这个报错,可以在调用super().__new__的那一行加# type: ignore注释,但这会掩盖潜在的类型问题,只适合临时测试用:
class B(A): def __new__(cls, x: str) -> 'B': return super().__new__(cls, int(x)) # type: ignore def log(self) -> None: print('Hello World')
内容的提问来源于stack exchange,提问作者VBK
相关产品推荐
相关产品推荐

