应优先使用 isinstance() 而非 type() 判断类型,因 isinstance() 遵循 mro、支持继承与 abc,体现鸭子类型哲学;type() 仅判别直接类型,适用极少数需严格身份校验的场景。

判断对象类型时,错误处理逻辑的核心不是“防错”,而是“选对方式”——用错方法(比如盲目用 type())本身就会成为错误源头。真正要处理的,是类型判断失败后程序该怎么做,而不是反复验证判断本身是否“正确”。
避免用 type() 做继承关系判断
直接比较 type(obj) == SomeClass 只认“亲生”,不认“子类”。哪怕 obj 是 SomeClass 的实例,只要它实际类型是子类,结果就是 False,这常被误认为“类型判断失败”,实则是逻辑设计错误。
- ❌ 错误写法:
if type(data) == list: ... - ✅ 正确写法:
if isinstance(data, list): ... - 子类、内置类型别名(如
collections.UserList)都能被isinstance正确识别
区分 None 和空值的类型检查
None 是单例对象,它的类型是 NoneType,但日常中更常见的是想确认“有没有值”,而非“是不是 None”。混淆这两者会导致防御性代码冗余或漏判。
- 判断是否为 None:用
obj is None(最安全),或isinstance(obj, type(None)) - 判断是否“无意义”:结合业务,如
not obj(注意字符串、数字、空容器也返回 True) - 避免写
type(obj) == type(None)—— 冗长且易出错
多重类型兼容时的异常兜底
当接受多种输入类型(如 str / bytes / Path)时,isinstance(obj, (str, bytes, pathlib.Path)) 能覆盖大多数情况。但若传入意外类型(比如 int 或自定义类),需明确后续行为:
- 转换尝试:
str(obj)或os.fspath(obj)(适合路径场景) - 抛出明确异常:
raise TypeError(f"Expected str, bytes or Path, got {type(obj).__name__}") - 静默忽略或默认值(仅限低风险场景,如日志字段)
动态类型场景下优先用协议而非类型
Python 是鸭子类型语言。比起问“它是什么类型”,更应问“它能不能做某件事”。例如判断能否迭代,用 hasattr(obj, '__iter__') 或 collections.abc.Iterable 比检查是否为 list 或 tuple 更健壮。
- 推荐:
isinstance(obj, collections.abc.Mapping)判断字典行为,而非只认dict - 避免硬编码类型列表,尤其在第三方库对象介入时(如 pandas.Series、numpy.ndarray)
- 必要时配合
getattr(obj, 'shape', None)等属性探测做柔性适配











