
1. 题目考点
这道题主要考:
itertools.product()的使用- 列表输入处理:
input().split() - 字符串转整数:
map(int, ...) - 元组输出格式
- 笛卡尔积的理解
这道题不是让你自己手写复杂算法,而是让你理解:两个列表 A 和 B 的所有组合怎么生成。
2. 审题
题目给你两个列表:
A = [1, 2]
B = [3, 4]
要求输出它们的笛卡尔积:
(1, 3) (1, 4) (2, 3) (2, 4)
也就是说:
先拿 A 里的第一个数 1,分别和 B 里的每个数配对:
(1, 3)
(1, 4)
再拿 A 里的第二个数 2,分别和 B 里的每个数配对:
(2, 3)
(2, 4)
所以整体结果是:
(1, 3) (1, 4) (2, 3) (2, 4)
注意,题目要求的是:
Output the space separated tuples
也就是输出“用空格分隔的元组”,不是输出列表。
所以不能直接输出:
[(1, 3), (1, 4), (2, 3), (2, 4)]
这个里面有中括号 [],不符合格式。
3. 思路提示
先不要急着写代码,可以这样想:
第一步,读入第一行,把它变成整数列表 A。
例如输入:
1 2
处理后应该得到:
A = [1, 2]
第二步,读入第二行,把它变成整数列表 B。
例如输入:
3 4
处理后应该得到:
B = [3, 4]
第三步,使用:
product(A, B)
生成所有组合。
它的效果等价于下面这种双重循环:
for a in A:
for b in B:
生成 (a, b)
第四步,把这些元组用空格分隔输出。
关键点是:
print(*product(A, B))
这里的 * 会把 product(A, B) 生成的多个元组一个一个展开,然后交给 print() 输出。
4. 完整设计思路
第一步:导入 product
因为 product() 在 itertools 模块里,所以要先写:
from itertools import product
第二步:读取列表 A
输入是一整行,例如:
1 2
input() 读进来是字符串:
"1 2"
使用 .split() 可以按空格切开:
["1", "2"]
但是此时里面还是字符串,不是整数。
所以要用:
map(int, input().split())
把每个字符串转成整数。
再用 list() 包起来,得到真正的列表:
A = list(map(int, input().split()))
第三步:读取列表 B
同理:
B = list(map(int, input().split()))
第四步:生成笛卡尔积并输出
product(A, B)
会生成:
(1, 3), (1, 4), (2, 3), (2, 4)
但是它本身是一个迭代器,不是直接显示出来的列表。
如果写:
print(product(A, B))
输出不会是你想要的结果。
如果写:
print(list(product(A, B)))
输出会带中括号:
[(1, 3), (1, 4), (2, 3), (2, 4)]
这也不符合题目格式。
正确做法是:
print(*product(A, B))
这样会输出:
(1, 3) (1, 4) (2, 3) (2, 4)
5. 代码实现
from itertools import product
A = list(map(int, input().split()))
B = list(map(int, input().split()))
print(*product(A, B))
这是本题最简洁、最符合题意的写法。
6. 运行演示
假设输入是:
1 2
3 4
程序第一行:
A = list(map(int, input().split()))
读入:
1 2
得到:
A = [1, 2]
程序第二行:
B = list(map(int, input().split()))
读入:
3 4
得到:
B = [3, 4]
然后:
product(A, B)
内部相当于这样运行:
A 里取 1,B 里依次取 3、4
得到 (1, 3)、(1, 4)
A 里取 2,B 里依次取 3、4
得到 (2, 3)、(2, 4)
最后:
print(*product(A, B))
输出:
(1, 3) (1, 4) (2, 3) (2, 4)
7. 这道题容易错在哪里
错误一:直接打印 list
例如:
print(list(product(A, B)))
输出是:
[(1, 3), (1, 4), (2, 3), (2, 4)]
这个有中括号,不符合题目要求。
题目要的是:
(1, 3) (1, 4) (2, 3) (2, 4)
所以应该用:
print(*product(A, B))
错误二:忘记把输入转成整数
如果写:
A = input().split()
B = input().split()
那么 A 和 B 里面是字符串:
A = ["1", "2"]
B = ["3", "4"]
输出会变成:
('1', '3') ('1', '4') ('2', '3') ('2', '4')
里面带引号,不符合题目要求。
所以必须使用:
map(int, input().split())
错误三:不知道 product 的顺序
product(A, B) 的顺序是:
for a in A:
for b in B:
print((a, b))
也就是第一个列表 A 的元素在外层循环,第二个列表 B 的元素在内层循环。
所以:
A = [1, 2]
B = [3, 4]
输出顺序是:
(1, 3) (1, 4) (2, 3) (2, 4)
不是:
(1, 3) (2, 3) (1, 4) (2, 4)
8. 方法总结
以后看到这类题,可以按这个思路下手:
如果题目让你求“两个列表所有可能的组合”,本质上就是笛卡尔积。
如果不用工具函数,通常是双重循环:
for a in A:
for b in B:
处理 (a, b)
如果题目明确出现在 itertools.product() 这一节,就优先使用:
product(A, B)
如果题目要求“空格分隔输出多个结果”,可以考虑:
print(*结果)
这一题的核心代码其实就是:
print(*product(A, B))
但是前提是你要先把输入正确处理成整数列表。
9. 同类型小练习
给你两个列表:
A = [1, 2, 3]
B = [5, 6]
请输出它们的笛卡尔积,格式如下:
(1, 5) (1, 6) (2, 5) (2, 6) (3, 5) (3, 6)
提示:
先用 input().split() 读取两行,再用 map(int, ...) 转成整数,最后用 product(A, B) 生成结果,用 print(*结果) 输出。
print(product(A, B)),这里面这个号是什么意思?
print(*product(A, B)) 里的 * 不是乘号
这一句:
print(*product(A, B))
里面的 * 表示:把一个可迭代对象里面的元素一个一个展开,作为多个参数传给函数。
它在这里不是数学里的乘法。
先看 product(A, B) 生成了什么
假设:
A = [1, 2]
B = [3, 4]
那么:
product(A, B)
会生成这些结果:
(1, 3)
(1, 4)
(2, 3)
(2, 4)
你可以把它暂时理解成类似这样一个东西:
[(1, 3), (1, 4), (2, 3), (2, 4)]
虽然严格来说 product(A, B) 返回的是一个迭代器,但初学阶段可以先理解为“里面装着很多元组”。
不加 * 会怎样?
如果写:
print(product(A, B))
它不会把里面的组合打印出来,而是会打印这个对象本身的信息,类似:
<itertools.product object at 0x...>
这不是题目想要的结果。
如果写:
print(list(product(A, B)))
输出会是:
[(1, 3), (1, 4), (2, 3), (2, 4)]
这个结果虽然看得懂,但是有中括号 [],题目不需要中括号。
加上 * 会怎样?
这一句:
print(*product(A, B))
相当于把:
product(A, B)
里面的每一个元组拿出来,变成 print() 的多个参数。
也就是等价于:
print((1, 3), (1, 4), (2, 3), (2, 4))
而 print() 默认会用空格分隔多个参数,所以输出就是:
(1, 3) (1, 4) (2, 3) (2, 4)
这正好符合题目要求。
用普通列表理解 *
先不看 product(),只看一个简单列表:
nums = [1, 2, 3]
如果写:
print(nums)
输出是:
[1, 2, 3]
因为你是把整个列表作为一个东西打印出来。
但是如果写:
print(*nums)
输出是:
1 2 3
因为 *nums 会把列表展开,相当于:
print(1, 2, 3)
所以可以这样记:
print(nums)
意思是:打印整个列表。
print(*nums)
意思是:把列表里的元素拆开,一个一个打印。
回到本题
本题中:
print(*product(A, B))
可以理解成:
第一步,product(A, B) 生成所有组合:
(1, 3), (1, 4), (2, 3), (2, 4)
第二步,* 把这些组合展开:
(1, 3) (1, 4) (2, 3) (2, 4)
第三步,print() 用空格把它们打印出来:
(1, 3) (1, 4) (2, 3) (2, 4)
一个很重要的总结
在函数调用里面,* 的作用通常叫做:
解包
展开
unpacking
它的意思是:
print(*some_list)
等价于:
print(some_list[0], some_list[1], some_list[2], ...)
所以本题中的:
print(*product(A, B))
等价于:
print((1, 3), (1, 4), (2, 3), (2, 4))
小练习
观察下面代码,先不要运行,判断输出结果是什么:
nums = [10, 20, 30]
print(nums)
print(*nums)
提示:
第一行是打印整个列表,第二行是把列表拆开后打印。



