迭代协议本身不直接执行扁平化,但通过实现__iter__方法可构建惰性扁平化器:递归判断元素是否为非字符串的可迭代对象,是则yield from委托,否则yield原子值;生成器函数写法更轻量,二者均符合协议且节省内存。

迭代协议本身不直接执行扁平化,但它为按需逐个访问嵌套结构中的元素提供了标准机制——关键在于实现 __iter__ 方法,让对象能被 for 循环或 iter() 消费。多维数组的扁平化若走迭代协议路线,核心是写一个**惰性、可迭代的扁平化器**,而不是一次性生成完整一维列表。
用 __iter__ 实现惰性扁平化迭代器
定义一个类,其 __iter__ 方法内部递归遍历嵌套结构,每次 yield 一个原子值。这样既节省内存,又符合 Python 迭代协议规范。
- 对每个元素判断是否为可迭代且非字符串类型(避免把
"abc"拆成'a','b','c') - 若是,则递归调用自身
__iter__并用yield from委托产出 - 若否,则直接
yield该元素
适用于任意嵌套深度的通用写法
以下是一个简洁可靠的实现:
from collections.abc import Iterable
<p>class Flattener:
def <strong>init</strong>(self, nested):
self.nested = nested</p><pre class="brush:php;toolbar:false;">def __iter__(self):
for item in self.nested:
if isinstance(item, Iterable) and not isinstance(item, (str, bytes)):
yield from Flattener(item) # 递归委托
else:
yield item使用示例
data = [1, [2, [3, 4]], 5, [[6]]] flat_iter = Flattener(data) print(list(flat_iter)) # [1, 2, 3, 4, 5, 6]
与生成器函数的等价写法
更轻量的方式是直接写一个生成器函数,它天然支持迭代协议:
- 函数返回的是生成器对象,该对象实现了
__iter__和__next__ - 无需定义类,适合一次性、无状态的扁平化场景
- 同样支持
for循环、list()、sum()等所有迭代消费方式
def flatten_iter(nested):
for item in nested:
if isinstance(item, Iterable) and not isinstance(item, (str, bytes)):
yield from flatten_iter(item)
else:
yield item
<h1>直接使用</h1><p>for x in flatten_iter([1, [2, 3], [[4, 5], 6]]):
print(x) # 逐个输出:1 2 3 4 5 6
注意边界与性能细节
迭代协议方案不是“万能快捷键”,需留意几个实际约束:
- 不能跳过某层或按特定顺序重组(如想先取所有叶子再取根,就得改逻辑)
- 无法像
numpy.ravel()那样共享底层内存;Python 列表迭代器总是产生新引用 - 递归深度受限于 Python 默认递归限制(约 1000 层),超深嵌套建议改用显式栈模拟
- 若只需一层拉平(如
[[1,2],[3,4]] → [1,2,3,4]),itertools.chain.from_iterable()更高效且语义明确

















