Python中类型注解为何出现<class 'float'>与'float'两种形式?
抽象基类与实现类类型注解差异问题解析
问题场景
对比抽象基类与实现类的类型注解时,使用inspect.getfullargspec()工具获取参数注解,发现二者存在明显差异:
示例代码
抽象基类与实现类代码:
import abc from typing import List, Tuple class Abstract(abc.ABC): @abc.abstractmethod def get_hscodes(self, *, confidence_threshold: float = 0.0, **kwargs): pass class Concrete(Abstract): def get_hscodes(self, *, confidence_threshold: float = 0.0, **kwargs): likely = self.get_likely_hscodes(confidence_threshold=confidence_threshold, **kwargs) return [i[0] if i else (None, 0.0) for i in likely] def get_likely_hscodes( self, *, confidence_threshold: float = 0.0, **kwargs ) -> List[List[Tuple]]: pass
执行检查代码:
import inspect print(inspect.getfullargspec(Abstract.get_hscodes)) print(inspect.getfullargspec(Concrete.get_hscodes))
结果差异
- 抽象基类方法
Abstract.get_hscodes的注解:{'confidence_threshold': <class 'float'>} - 实现类方法
Concrete.get_hscodes的注解:{'confidence_threshold': 'float'}
测试环境为Python 3.8.13(Windows、Linux均出现该情况),且该问题难以稳定复现。
差异原因
abc.abstractmethod装饰器的处理逻辑
当方法被@abc.abstractmethod装饰时,装饰器会直接保留原始的类型注解对象(即实际的float类),不会对注解做字符串化处理。抽象方法的装饰逻辑更注重保留方法的原始元信息,因此注解以类型对象形式存储。Python 3.8的类型注解延迟解析机制
Python 3.8支持PEP 484定义的字符串形式类型注解(延迟评估),如果实现类的方法在加载或执行过程中,没有触发注解的解析逻辑(比如未调用typing.get_type_hints()、没有类型检查工具主动解析),注解就会以字符串'float'的形式保留。而普通方法没有像抽象方法那样的特殊元信息处理,更容易保留字符串形式的注解。不稳定复现的诱因
该问题难以稳定复现,是因为触发注解解析的场景具有随机性:- 代码加载顺序不同,可能导致某些模块提前触发了注解解析;
- IDE后台类型检查、自动化测试工具、第三方依赖库可能会隐式调用注解解析逻辑,将字符串形式的注解转换为类型对象;
- 不同环境下的模块缓存机制(如
.pyc文件)也会影响注解的存储形式。
另外,Python 3.9及以上版本对类型注解的处理机制做了优化,inspect模块获取注解的逻辑更统一,这类不一致的情况会大幅减少。
内容的提问来源于stack exchange,提问作者Chr1s
相关产品推荐
相关产品推荐

