应优先使用 isinstance() 而非 type() 做类型判断,因 isinstance() 遵循 MRO、支持继承与 ABC,体现鸭子类型哲学;type() 仅判别直接类型,适用极少数需严格身份校验的场景。
用 isinstance() 而不是 type()
直接比较 type(obj) == SomeClass 在绝大多数场景下是错的——它无法识别子类实例。比如 isinstance(42, int) 返回 True,但 type(42) == int 虽然也成立,一旦换成自定义子类:class MyInt(int): pass,那么 type(MyInt()) == int 就是 False,而 isinstance(MyInt(), int) 仍是 True。
这是因为它只检查对象的**直接类型**,不考虑继承链;而 isinstance() 按照 MRO(方法解析顺序)向上查找,符合 Python 的“鸭子类型”哲学和实际使用习惯。
传入类名时注意元组与单个类的区别
isinstance() 第二个参数支持单个类或类的元组。写成 isinstance(obj, (int, float)) 是合法的,但写成 isinstance(obj, int, float)(逗号分隔、无括号)会报 TypeError: isinstance() takes 2 arguments (3 given)。
- 要检查多个类型,必须用元组:
(int, str, list),不能用列表或集合 - 如果只检查一个类,
isinstance(obj, int)和isinstance(obj, (int,))效果一样,但后者多了一对括号和逗号,容易误写成(int)——这在 Python 中等价于int,不是元组 - 常见低级错误:
isinstance(obj, (int))看似像元组,实为 int 类型字面量,运行时不会报错但逻辑失效
特殊内置类型需小心:None、bool、数字字面量
None 是 NoneType 的唯一实例,但你不能直接写 NoneType(它未暴露在 builtins 中),得用 type(None) 或更稳妥地写 obj is None。
bool 是 int 的子类,所以 isinstance(True, int) 是 True。如果你只想区分布尔值和整数,不能只靠 isinstance(obj, bool),因为 isinstance(1, bool) 是 False(1 不是 bool 实例),但 isinstance(True, int) 是 True——这意味着检查顺序很重要:先查 bool,再查 int。
Python 3.14.3
微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。
- 判断是否为布尔值:
isinstance(obj, bool)安全,因为True/False是仅有的两个bool实例 - 判断是否为纯整数(不含
bool):isinstance(obj, int) and not isinstance(obj, bool) - 数字字面量如
3.14是float,但3.0也是float,不是int;即便它数值上等于整数,类型仍固定
自定义类继承与 __instancecheck__ 的影响
极少数库(如 typing 中的某些抽象基类)会重载 __instancecheck__ 方法来改变 isinstance() 行为。例如 isinstance([], typing.Sequence) 返回 True,尽管 list 并未显式继承 Sequence。
这种机制是隐式的、不可见的,调试时容易困惑:
- 普通类不会触发该逻辑,只有实现了
__instancecheck__的类(通常是 ABC)才会影响结果 - 如果你发现
isinstance(obj, SomeClass)返回意料之外的True,先确认SomeClass是否来自typing或collections.abc - 想绕过这种动态检查?基本做不到——
isinstance()的语义就包含对 ABC 的支持,这是语言设计的一部分
真正难处理的是混合了 ABC 和具体类的判断,比如 isinstance(x, (str, typing.Hashable)),此时只要满足任一条件即为真,但背后逻辑已脱离简单“是不是这个类”的直觉。
就爱读