
name, *line = input().split() 到底是怎么工作的
这一句其实是在做两件事:
先把用户输入的一整行,按空格切开;然后把切开后的结果“拆开”分给不同变量。
你看到的代码是:
name, *line = input().split()
可以把它先拆成两步理解:
data = input().split()
name = data[0]
line = data[1:]
也就是说,这种带 * 的写法,本质上就是一种更紧凑的“拆包”写法。
先看 input().split() 产生了什么
假设用户输入这一行:
Krishna 67 68 69
那么:
input().split()
得到的是一个列表:
['Krishna', '67', '68', '69']
注意,这里面每一项都是字符串,哪怕看起来像数字,实际上还是字符串。
所以这时候如果写:
name, *line = ['Krishna', '67', '68', '69']
它就会这样分配:
name接收第一个元素:'Krishna'line接收剩下所有元素:['67', '68', '69']
所以最后结果是:
name = 'Krishna'
line = ['67', '68', '69']
星号拆包是什么意思
最直白的理解
在赋值拆包里,*变量名 的意思是:
“把剩下没分完的所有元素,都收集到这个变量里,并且装成一个列表。”
所以:
name, *line = ['Krishna', '67', '68', '69']
等价于:
name = 'Krishna'
line = ['67', '68', '69']
这里的 line 不再是单个值,而是一个列表。
为什么这里要用 *line
因为这一行输入里:
- 第一个内容是学生名字
- 后面的内容都是成绩
也就是说,程序想表达的是:
“第一个单独拿出来当名字,剩下的全部当成绩列表。”
这时候 *line 就特别合适。
如果不用星号,你就得手动切片:
data = input().split()
name = data[0]
line = data[1:]
两种写法都对,只是星号拆包写得更紧凑一些。
执行过程一步一步模拟
来看这段:
name, *line = input().split()
scores = list(map(float, line))
student_marks[name] = scores
假设输入是:
Malika 52 56 60
第一步:读取并切分输入
input().split()
得到:
['Malika', '52', '56', '60']
第二步:星号拆包
name, *line = ['Malika', '52', '56', '60']
结果:
name = 'Malika'
line = ['52', '56', '60']
第三步:把字符串成绩变成浮点数
scores = list(map(float, line))
等价理解为:
scores = [52.0, 56.0, 60.0]
第四步:存到字典里
student_marks[name] = scores
结果字典会变成:
{
'Malika': [52.0, 56.0, 60.0]
}
如果前面还录入了其他学生,那么字典就会不断增加键值对。
map 到底起什么作用
一句话理解
map 的作用是:
把某个函数,依次作用到一组数据中的每一个元素上。
它的基本形式是:
map(函数, 可迭代对象)
比如:
line = ['52', '56', '60']
map(float, line)
意思就是:
- 把
float('52') - 把
float('56') - 把
float('60')
依次做一遍。
结果相当于把每个字符串都转换成浮点数。
这里为什么写 map(float, line)
因为 line 里现在还是字符串:
['52', '56', '60']
但我们后面要算平均分,必须把它们变成数字。
所以:
map(float, line)
就是把列表里的每个字符串都变成 float 类型。
再配合 list(...):
scores = list(map(float, line))
最终得到:
[52.0, 56.0, 60.0]
为什么还要再套一层 list()
这是因为在 Python 3 里,map() 返回的不是直接的列表,而是一个 map 对象。
你可以先把它理解成:
“一个还没真正展开的转换结果”
所以通常我们会写成:
list(map(float, line))
把它真正变成列表。
和熟悉的写法对比一下
已经知道这种写法:
data = input().split()
name = data[0]
scores = list(map(float, data[1:]))
这和题目中的写法:
name, *line = input().split()
scores = list(map(float, line))
本质上是一样的。
第一种写法:更直白
data = input().split()
name = data[0]
scores = list(map(float, data[1:]))
优点是初学者更容易看懂,因为每一步都展开了。
第二种写法:更紧凑
name, *line = input().split()
scores = list(map(float, line))
优点是代码更简洁,更像“第一个给名字,其余都给成绩”。
对于初学者来说,我建议你先把第二种写法自动翻译成第一种写法去理解。这样会稳很多。
最小可运行例子
你可以先单独跑这个小例子,观察变量到底变成了什么:
data = "Krishna 67 68 69".split()
print(data)
name, *line = data
print(name)
print(line)
scores = list(map(float, line))
print(scores)
运行结果大概是:
['Krishna', '67', '68', '69']
Krishna
['67', '68', '69']
[67.0, 68.0, 69.0]
从思路到代码
这道题里,人脑的思路其实是这样的:
先读入一整行数据。
这一行里,第一个是名字,后面几个是分数。
名字要单独保存,分数要收集起来。
因为输入进来的分数本来是字符串,所以还要把它们转成数字。
最后把“名字 -> 分数列表”存进字典。
把这个思路翻译成代码,就是:
name, *line = input().split()
scores = list(map(float, line))
student_marks[name] = scores
所以你可以把这句理解成:
“先切开;第一个给名字;剩下的给成绩;再把成绩从字符串改成数字;最后存进字典。”
再补几个星号拆包的例子
例 1:收集后面的所有元素
a, *b = [1, 2, 3, 4]
结果:
a = 1
b = [2, 3, 4]
例 2:前后都可以留位置
a, *b, c = [1, 2, 3, 4, 5]
结果:
a = 1
b = [2, 3, 4]
c = 5
这里的 *b 表示:
中间剩下的都给 b。
例 3:只有一个剩余元素时
a, *b = [10, 20]
结果:
a = 10
b = [20]
例 4:后面没有剩余元素时
a, *b = [10]
结果:
a = 10
b = []
注意,b 仍然是列表,只不过是空列表。
常见错误与易混点
1. 以为 line 是一个字符串
不是。
name, *line = input().split()
这里的 line 是一个列表,不是单个字符串。
2. 以为 map(float, line) 会直接得到列表
在 Python 3 里不是直接列表,而是 map 对象。
通常都要这样写:
scores = list(map(float, line))
3. 忘了输入的数据本来都是字符串
input() 读进来的内容默认都是字符串。
所以:
'67'
不是数字 67,必须转换。
4. 不知道 *line 为什么能接多个值
因为带星号的变量,在拆包赋值时专门负责“收集剩余元素”。
并且收集出来的一定是列表。
你可以把这句翻译成“人话”
name, *line = input().split()
可以翻译成:
“把输入按空格拆开,第一个内容放到 name 里,剩下所有内容放到 line 这个列表里。”
而这句:
scores = list(map(float, line))
可以翻译成:
“把 line 里面每一个字符串成绩,都转成浮点数,再组成一个列表。”
本节小结
这段代码里最关键的两个点是:
星号拆包
name, *line = input().split()
表示:
name接第一个元素line接剩下全部元素line是一个列表
map 的作用
list(map(float, line))
表示:
- 对
line里的每个元素都执行一次float() - 把字符串数字变成浮点数
- 最后再转成列表
所以整段连起来就是:
name, *line = input().split()
scores = list(map(float, line))
意思是:
从一行输入里拿到名字和分数,并把分数字符串转换成数字列表。
练习
请你自己先不要看答案,试着写一段小程序:
题目:
用户输入一行:
Tom 80 90 100
要求你完成下面几件事:
- 用星号拆包拿到名字和分数部分
- 把分数字符串转换成整数列表
- 打印名字
- 打印分数列表
提示:
- 先用
input().split() - 第一个元素给名字
- 剩下的给列表
- 可以试着用
map(int, ...)



