int子类__new__方法意外类型警告的原因及优化方案
问题解答
1. 警告产生的原因
PyCharm的静态类型检查是基于int.__new__的类型签名判断的。Python官方给int.__new__的类型注解里,第一个非类参数被标注为str | bytes | bytearray,但实际运行中int构造函数是支持接收int类型参数的(比如int(123)完全合法)。这种静态检查签名和实际运行逻辑的不一致,导致PyCharm抛出了类型不匹配的警告。
2. 为什么super(Size, cls).__new__ == int.__new__为True却提示不接受int?
虽然super(Size, cls).__new__确实指向int.__new__,但静态类型检查只认函数的类型注解签名,不管实际运行时的参数处理逻辑。int.__new__的类型注解只声明了接受字符串类类型,所以PyCharm会按这个签名做检查,哪怕实际运行时int.__new__能处理int参数。本质是静态检查和运行时逻辑“脱钩”了。
3. 创建支持多输入类型的int子类的更优方式
要实现像Size(1024)或Size('1 KiB')这样的多实例化方式,可按以下思路实现:
- 重写
__new__方法,先对输入参数做类型判断和转换:- 如果是int,直接保留或做数值处理
- 如果是字符串,解析成对应的目标数值(比如处理'KiB'这类单位)
- 用
@overload标注不同的构造重载,让静态类型检查器识别合法的输入类型 - 最后调用父类
__new__时,确保传入的参数符合int.__new__的处理逻辑
示例代码:
from typing import overload, Union class Size(int): @overload def __new__(cls, value: int) -> 'Size': ... @overload def __new__(cls, value: str) -> 'Size': ... def __new__(cls, value: Union[int, str]): if isinstance(value, str): # 解析带单位的字符串,比如'1 KiB'转为1024 num_str, unit = value.strip().split() num = float(num_str) unit_map = {'KiB': 1024, 'MiB': 1024**2, 'GiB': 1024**3} value = int(num * unit_map[unit]) # 将处理后的数值传给父类__new__ return super().__new__(cls, value)
这样既实现了自定义实例化逻辑,又能让IDE识别合法输入类型,避免不必要的警告。
内容的提问来源于stack exchange,提问作者Grismar
相关产品推荐
相关产品推荐

