应优先用type(obj).__name__获取真实类型名,因__class__可被篡改;泛型需用__origin__.__name__或typing.get_origin();类名不含模块路径,完整路径需拼接__module__和__name__。

直接用 obj.__class__.__name__ 就行,但要注意它返回的是类名字符串,不是完整模块路径,且对内置类型、代理对象、泛型别名等行为不一致。
为什么不用 type(obj).__name__?
多数情况下 type(obj).__name__ 和 obj.__class__.__name__ 效果一样,但存在关键差异:
-
obj.__class__可被子类或元类重写(比如某些 ORM 模型或 mock 对象会动态替换__class__),而type(obj)始终返回运行时真实类型 - 对
None、int等内置常量,两者结果相同;但对自定义类实例,若显式修改了__class__属性(不推荐但合法),obj.__class__.__name__会返回篡改后的类名,type(obj).__name__仍返回原始类型名 - 性能上几乎无差别,无需刻意优化
__class__.__name__ 在泛型和类型提示中失效
遇到 list[int]、dict[str, Any] 或 Optional[str] 这类类型提示对象时,__class__.__name__ 会返回 'GenericAlias' 或 'UnionType',而不是你期望的 'list' 或 'Union':
>>> from typing import List, Union >>> t = List[int] >>> t.__class__.__name__ 'GenericAlias' >>> t.__origin__.__name__ # 正确获取基础类型名 'list' >>> u = Union[int, str] >>> u.__class__.__name__ 'UnionType' >>> u.__args__ # 需手动拆解 (<class>, <class>) </class></class>
这类场景下不能只依赖 __class__.__name__,得结合 __origin__、__args__ 或 typing.get_origin()/get_args() 判断。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
常见错误:把类名当模块路径用
__class__.__name__ 只返回类名,不包含模块信息。比如 datetime.datetime 实例返回的是 'datetime',不是 'datetime.datetime':
- 需要完整路径时,用
f"{obj.__class__.__module__}.{obj.__class__.__name__}" - 但注意:
__module__可能是'builtins'(如str)、'__main__'(交互式环境或脚本顶层定义的类),甚至None(极少数 C 扩展类) - 跨模块导入后,类的
__module__仍是定义处的模块名,不是导入处的模块名 —— 这是 Python 的设计逻辑,不是 bug
真正麻烦的是那些动态生成的类(比如 namedtuple、dataclass、Pydantic 模型),它们的 __name__ 可能带下划线前缀或数字后缀,且 __module__ 可能为 '_collections' 或 'pydantic.main',跟直觉不符。这时候光看名字很难反推来源,得结合调试器或 inspect.getfile() 辅助判断。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










