最稳妥方式是用 isinstance(obj, collections.abc.iterable),它语义清晰、开销小、兼容性好,能正确识别各类可迭代对象,但需注意 str 和 bytes 默认视为可迭代;备用方案是 iter(obj) 捕获 typeerror,适用于验证实际迭代行为。

最稳妥、符合 Python 惯用法的方式是用 isinstance(obj, collections.abc.Iterable)。
推荐:用 collections.abc.Iterable 做类型检查
这是官方推荐、语义清晰、开销小且兼容性好的方法。
- 从
collections.abc导入Iterable(注意不是collections.Iterable,后者在 Python 3.12+ 已弃用) - 调用
isinstance(obj, Iterable),返回True表示对象实现了迭代协议 - 它能正确识别
list、tuple、dict、set、str、bytes、生成器、自定义类(只要实现了__iter__或注册了 ABC) - 注意:
str和bytes默认算可迭代,如果业务上希望把它们当“原子值”处理,需额外排除
备用:用 iter() + 异常捕获验证运行时行为
当你需要确认对象“真能被 for 循环用”,而不仅是类型注册状态时,适合用此法。
- 直接调用
iter(obj) - 若成功返回迭代器,说明可迭代;若抛出
TypeError,则不可迭代 - 务必只捕获
TypeError,避免掩盖其他异常 - 不建议用于高频前置判断——异常机制有开销,且可能触发副作用(如生成器初始化)
谨慎使用:检查 __iter__ 是否存在且可调用
适用于无法导入 abc 模块的极简环境(如某些嵌入式 Python),但需手动规避陷阱。
- 先
hasattr(obj, '__iter__'),再callable(getattr(obj, '__iter__')) - 不能仅靠
hasattr(obj, '__iter__'),因为有些类把__iter__定义为属性而非方法 - 该方式不识别仅靠
__getitem__支持旧式序列迭代的对象(Python 已基本淘汰这类设计)
明确要避免的方法
这些看似直观的做法实际不可靠,容易误判或引发意外行为。
- 别写
for _ in obj: break来试探——这会真实执行一次迭代,可能消耗生成器、触发网络请求或抛出异常 - 别用
len(obj)是否报错来反推——len和迭代协议正交,比如空列表可迭代但len为 0,某些类有__len__却没__iter__ - 别检查
__getitem__是否存在并尝试obj[0]——既不符合 PEP 234,又可能索引越界或触发副作用











