itertools.product 是多列表笛卡尔积的标准解法,需解包传参、支持 repeat 参数,返回内存友好的迭代器,结果为元组,空列表参与时结果为空。

用 itertools.product 做多列表笛卡尔积最稳
直接上结论:多个列表求笛卡尔积,itertools.product 是标准解法,不造轮子、不写嵌套循环、不手动递归。它返回的是迭代器,内存友好,也支持 repeat 参数做自身乘积。
常见错误是把列表当参数直接传进去,比如 product([[1,2], [3,4]]) —— 这样只会得到两个元组:(([1, 2],), ([3, 4],)),根本不是笛卡尔积。正确做法是解包:
-
list(product([1,2], [3,4]))→[(1, 3), (1, 4), (2, 3), (2, 4)] - 三个列表:
product([1,2], ['a'], [True, False]) - 动态数量?用
*lists解包:product(*list_of_lists)
嵌套列表太多时,repeat 比重复写参数更安全
比如要算 [0,1] × [0,1] × [0,1](即所有 3 位二进制组合),写三遍 [0,1] 容易漏或错位。用 repeat=3 更清晰且可变:
-
product([0,1], repeat=3)→ 生成 8 个元组,如(0,0,0)、(0,0,1)… -
repeat只对单个可迭代对象生效,不能和多个不同列表混用;混用会报TypeError: product() got multiple values for argument 'repeat' - 如果硬要混合(比如
[0,1]重复两次,再拼一个['x','y']),只能显式写成product([0,1], [0,1], ['x','y'])或用*([0,1] * 2 + [['x','y']])(注意内层要包成列表)
结果是元组,不是列表,别在循环里反复转 list()
product 返回的每个元素都是 tuple,不是 list。有人习惯在循环中写 list(item) 再操作,其实多数场景没必要——元组支持索引、解包、成员检查,性能还略好。
立即学习“Python免费学习笔记(深入)”;
- 需要修改元素?先转
list(item),但得清楚这是新建对象 - 要拼接字符串?
''.join(map(str, item))直接可用,不用先转 list - 误以为
product返回 list 导致内存爆掉:它返回迭代器,list(product(...))才真正展开。大数据量时务必避免无脑list()
和手写循环比,product 的边界行为更确定
空列表参与笛卡尔积时,结果是空迭代器(长度为 0),不会报错也不会返回意外值。而手写多层 for 循环容易在某层为空时逻辑断裂或漏处理。
-
product([1,2], [])→ 空结果(for循环直接不进内层) -
product([], [], [3])→ 同样为空,符合数学定义 - 含
None或不可迭代对象?会立刻抛TypeError: 'NoneType' object is not iterable,比静默出错更容易定位 - Python 3.12+ 对超大
repeat值会触发OverflowError,提前暴露组合爆炸风险
嵌套层级一深,手写循环的缩进、变量名、break/continue 控制就容易出岔子;product 把逻辑收进一个调用里,反而更不容易错——但得记牢解包这个动作,这是最多人卡住的地方。









