itertools.product
本文最后更新于25 天前,其中的信息可能已经过时,如有错误请发送邮件到184874483@qq.com

1. 题目考点

这道题主要考:

  1. itertools.product() 的使用
  2. 列表输入处理:input().split()
  3. 字符串转整数:map(int, ...)
  4. 元组输出格式
  5. 笛卡尔积的理解

这道题不是让你自己手写复杂算法,而是让你理解:两个列表 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)

提示:

第一行是打印整个列表,第二行是把列表拆开后打印。

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇