零基础学 Python 第8章 | 字符串操作与格式化输出
本章摘要
- 核心目标:掌握字符串切片与常用方法,学会三种格式化输出,能独立生成格式化成绩单
- 核心知识点:字符串切片、
upper/lower/strip/replace/split/join/find/count、%格式化、format方法、f-string - 实操产出:学生成绩存储与查询小工具(第二部分毕业综合案例)
- 前置基础:第7章字典、第5-6章循环与列表
一、写在前面
上一章我们学了字典,能以键值对的方式存储和查找数据。到这一章为止,你已经掌握了变量、条件判断、循环、列表和字典——Python 编程的核心地基已经打好了。
但你有没有注意到一个细节?从第1章的 print("Hello World") 开始,字符串就一直陪伴着我们。之前我们只是简单地用字符串存名字、存城市名,最多用 + 拼接一下。其实字符串远不止于此:
- 从一段文字中截取中间几个字 → 切片
- 把用户输入的多余空格去掉 →
strip - 把一句话按空格拆成单词列表 →
split - 把成绩、姓名整齐地填进一行报告里 → 格式化输出
这些操作在实际编程中天天用到。本章就来系统学习字符串的切片、常用方法和三种格式化输出方式,最后用一个"学生成绩存储与查询小工具"串联第二部分全部知识,完成循环与容器篇的毕业挑战。
二、字符串切片
2.1 字符串是不可变的序列
先记住一个结论:字符串就是一串字符按顺序排列组成的序列,每个字符都有自己的编号(索引)。
name = "Python"
print(name[0]) # P,第1个字符,索引为0
print(name[1]) # y,第2个字符,索引为1
print(name[5]) # n,第6个字符,索引为5
Python 的索引从 0 开始,这和列表完全一样。除了正序索引,还支持负数索引——从末尾往前数,最后一个字符是 -1,倒数第二个是 -2,以此类推:
name = "Python"
print(name[-1]) # n,最后一个
print(name[-2]) # o,倒数第二个
print(name[-6]) # P,第一个(和 name[0] 等价)
2.2 切片语法:[起:止]
切片就是从字符串中"截取一段"。语法是 字符串[起始:结束],包含起始位置,不包含结束位置(左闭右开):
text = "HelloPython"
print(text[0:5]) # Hello,索引0~4
print(text[5:11]) # Python,索引5~10
几个常用简写:
text = "HelloPython"
print(text[:5]) # Hello,省略起始=从头开始
print(text[5:]) # Python,省略结束=到末尾
print(text[:]) # HelloPython,都省略=完整复制
2.3 带步长的切片:[起:止:步长]
切片还可以加第三个参数——步长,决定每隔几个字符取一次:
text = "HelloPython"
print(text[0:11:2]) # HloPto,每隔1个取1个(步长2)
print(text[::2]) # HloPto,从头到尾步长2
print(text[::-1]) # nohtyPolleH,步长-1=反转字符串
[::-1]反转字符串是一个非常实用的技巧,记住它。
2.4 字符串不可变
字符串一旦创建,里面的字符不能通过索引修改:
name = "Python"
# name[0] = "J" # 取消注释运行会触发 TypeError: 'str' object does not support item assignment
想修改怎么办?用后面要学的 replace 方法生成一个新字符串,或者用切片拼接:
name = "Python"
new_name = "J" + name[1:] # Jython
print(new_name)
三、常用字符串方法
字符串自带了很多"方法"(可以理解为字符串专属的函数),用 字符串.方法名() 调用。下面学习最常用的 8 个。
3.1 upper() 和 lower():大小写转换
upper() 把所有字母转大写,lower() 转小写:
text = "Hello World"
print(text.upper()) # HELLO WORLD
print(text.lower()) # hello world
方法不会改变原字符串,而是返回一个新字符串。原变量
text的值不变。
3.2 strip():去除首尾空白
用户输入时经常多打空格,strip() 能去掉字符串首尾的空格、制表符和换行符:
raw_input = " 张三 "
clean = raw_input.strip()
print(f"[{clean}]") # [张三]
还有 lstrip()(只去左边)和 rstrip()(只去右边),用法一样。
3.3 replace():替换
replace(旧, 新) 把字符串中的指定内容替换成新内容:
sentence = "我喜欢吃苹果,苹果很好吃"
new_sentence = sentence.replace("苹果", "香蕉")
print(new_sentence) # 我喜欢吃香蕉,香蕉很好吃
第三个参数可以限制替换次数:
sentence = "苹果苹果苹果"
print(sentence.replace("苹果", "香蕉", 2)) # 香蕉香蕉苹果,只替换前2个
3.4 split():拆分
split() 把字符串按指定分隔符拆成列表,非常常用:
info = "张三,18,北京,编程"
parts = info.split(",")
print(parts) # ['张三', '18', '北京', '编程']
print(parts[0]) # 张三
不传参数时默认按空白(空格、换行)拆分:
sentence = "Hello Python World"
words = sentence.split()
print(words) # ['Hello', 'Python', 'World']
3.5 join():合并
join() 是 split() 的逆操作,把列表里的字符串用指定分隔符拼成一个字符串:
words = ["Hello", "Python", "World"]
sentence = " ".join(words)
print(sentence) # Hello Python World
# 用逗号拼接
csv_line = ",".join(words)
print(csv_line) # Hello,Python,World
注意调用方式:是
分隔符.join(列表),不是列表.join(分隔符)。
3.6 find():查找
find(子串) 返回子串第一次出现的索引,找不到返回 -1:
text = "Hello Python"
pos = text.find("Python")
print(pos) # 6,从索引6开始
pos = text.find("Java")
print(pos) # -1,没找到
3.7 count():计数
count(子串) 返回子串出现的次数:
text = "苹果香蕉苹果葡萄苹果"
print(text.count("苹果")) # 3
print(text.count("香蕉")) # 1
print(text.count("西瓜")) # 0
3.8 方法速览表
| 方法 | 功能 | 示例 | 结果 |
|---|---|---|---|
upper() |
全部转大写 | "abc".upper() |
"ABC" |
lower() |
全部转小写 | "ABC".lower() |
"abc" |
strip() |
去首尾空白 | " hi ".strip() |
"hi" |
replace(a, b) |
把 a 替换成 b | "a-b".replace("-", "+") |
"a+b" |
split(sep) |
按分隔符拆成列表 | "a,b,c".split(",") |
['a','b','c'] |
join(列表) |
用分隔符拼接列表 | "-".join(['a','b']) |
"a-b" |
find(子串) |
查找子串位置 | "abc".find("b") |
1 |
count(子串) |
统计子串出现次数 | "aba".count("a") |
2 |
记住一个规律:字符串方法都不会修改原字符串,而是返回一个新字符串。如果想保存结果,记得用变量接收:
text = text.strip()。
四、格式化输出
格式化输出就是把变量值"填入"一段文字模板中。Python 有三种方式,从老到新依次是:% 格式化、format() 方法、f-string。
4.1 % 格式化(最古老)
用 %s(字符串)、%d(整数)、%f(浮点数)做占位符,类似 C 语言的 printf:
name = "小明"
age = 18
score = 95.5
print("姓名:%s,年龄:%d,成绩:%.1f" % (name, age, score))
# 姓名:小明,年龄:18,成绩:95.5
%.1f表示保留1位小数,%.2f保留2位,以此类推。
这种方式现在不推荐日常使用,但你在看老代码时会经常遇到,需要能看懂。
4.2 format() 方法
用 {} 做占位符,调用 format() 方法填入值:
name = "小明"
age = 18
score = 95.5
print("姓名:{},年龄:{},成绩:{:.1f}".format(name, age, score))
# 姓名:小明,年龄:18,成绩:95.5
{} 里可以加序号来指定顺序:
print("{0}今年{1}岁,{0}在学Python".format("小明", 18))
# 小明今年18岁,小明在学Python
{:.1f} 的含义:冒号后是格式说明,.1f 表示保留1位小数。
4.3 f-string(推荐)
Python 3.6 引入,最简洁直观,日常首选:
name = "小明"
age = 18
score = 95.5
print(f"姓名:{name},年龄:{age},成绩:{score:.1f}")
# 姓名:小明,年龄:18,成绩:95.5
在字符串前加 f,花括号 {} 里直接写变量名或表达式:
# 直接写表达式
a, b = 3, 4
print(f"{a} + {b} = {a + b}") # 3 + 4 = 7
# 保留小数
price = 19.99
print(f"价格:{price:.2f} 元") # 价格:19.99 元
# 对齐填充
name = "张三"
print(f"{'姓名':<6}|{'成绩':>6}") # 左对齐6位 | 右对齐6位
4.4 三种方式对比
| 方式 | 写法 | 特点 |
|---|---|---|
% 格式化 |
"你好 %s" % name |
最老,能看懂即可 |
format() |
"你好 {}".format(name) |
较灵活,适合模板复用 |
| f-string | f"你好 {name}" |
最简洁,日常首选 |
结论:自己写代码用
f-string,看老代码能读懂%和format就行。前面章节其实已经在用f-string了,现在你正式学会它了。
五、Scratch 积木对照
| Scratch | Python | 说明 |
|---|---|---|
| 「连接」积木(apple banana) | 字符串 + 字符串 或 f"{a}{b}" |
把两段文字拼在一起 |

# Scratch「连接」积木 → Python 对照
first = "Hello"
second = "World"
# 方式1:用 + 拼接
print(first + " " + second) # Hello World
# 方式2:用 f-string
print(f"{first} {second}") # Hello World
Scratch 的「连接」积木把两块文字粘到一起,Python 里用 + 拼接或 f-string 直接嵌入,效果一样,但 f-string 更灵活——想插几个变量就写几个 {}。
六、综合实战:学生成绩存储与查询小工具(第二部分毕业案例)
这是第二部分(循环与容器篇)的综合毕业案例,综合运用第4-8章全部知识:列表 + 字典 + for/while 循环 + 条件判断 + 字符串格式化。
功能设计:
- 录入学生姓名和成绩,存入字典
- 按条件查询(及格/不及格/全部)
- 统计平均分、最高分、最低分
- 格式化输出成绩单
# ========================================
# 学生成绩存储与查询小工具
# 综合运用:列表 + 字典 + for/while 循环 + 条件判断 + 字符串格式化
# ========================================
# 用列表存储所有学生,每个学生是一个字典
students = []
print("=" * 40)
print(" 学生成绩存储与查询系统 v1.0")
print("=" * 40)
# 1. 录入学生信息
while True:
print()
name = input("请输入学生姓名(输入 q 结束录入):").strip()
if name.lower() == "q":
break
score = float(input(f"请输入 {name} 的成绩(0-100):"))
if score < 0 or score > 100:
print("⚠️ 成绩无效,请重新录入该学生")
continue
# 每个学生存为一个字典,追加到列表
student = {"姓名": name, "成绩": score}
students.append(student)
print(f"✅ 已录入:{name} - {score} 分")
# 2. 查询功能
print()
print("=" * 40)
print(" 查询菜单")
print(" 1. 查看全部成绩")
print(" 2. 查看及格的学生(>=60)")
print(" 3. 查看不及格的学生(<60)")
print(" 4. 按姓名搜索")
print("=" * 40)
choice = input("请选择查询方式(1-4):")
# 3. 根据选择筛选数据
if choice == "1":
result = students
title = "全部学生成绩"
elif choice == "2":
result = [s for s in students if s["成绩"] >= 60]
title = "及格学生成绩"
elif choice == "3":
result = [s for s in students if s["成绩"] < 60]
title = "不及格学生成绩"
elif choice == "4":
search_name = input("请输入要搜索的姓名:").strip()
result = [s for s in students if search_name in s["姓名"]]
title = f"搜索「{search_name}」的结果"
else:
result = []
title = "无效选择"
# 4. 格式化输出成绩单
print()
print("=" * 40)
print(f" {title}")
print("=" * 40)
print(f"{'序号':<6}{'姓名':<10}{'成绩':<8}{'等级':<6}")
print("-" * 40)
if len(result) == 0:
print(" 暂无数据")
else:
for i, s in enumerate(result, 1):
# 根据成绩判定等级
if s["成绩"] >= 90:
grade = "优秀"
elif s["成绩"] >= 80:
grade = "良好"
elif s["成绩"] >= 60:
grade = "及格"
else:
grade = "不及格"
# f-string 格式化输出,< 表示左对齐
print(f"{i:<6}{s['姓名']:<10}{s['成绩']:<8.1f}{grade:<6}")
print("-" * 40)
# 5. 统计信息(基于全部学生)
if len(students) > 0:
scores = [s["成绩"] for s in students]
avg = sum(scores) / len(scores)
max_score = max(scores)
min_score = min(scores)
pass_count = sum(1 for s in scores if s >= 60)
print(f" 总人数:{len(students)} 人")
print(f" 平均分:{avg:.1f}")
print(f" 最高分:{max_score:.1f}")
print(f" 最低分:{min_score:.1f}")
print(f" 及格率:{pass_count}/{len(students)}({pass_count/len(students)*100:.0f}%)")
else:
print(" 未录入任何学生数据")
print("=" * 40)
运行效果:
========================================
学生成绩存储与查询系统 v1.0
========================================
请输入学生姓名(输入 q 结束录入):张三
请输入 张三 的成绩(0-100):95
✅ 已录入:张三 - 95.0 分
请输入学生姓名(输入 q 结束录入):李四
请输入 李四 的成绩(0-100):58
✅ 已录入:李四 - 58.0 分
请输入学生姓名(输入 q 结束录入):王五
请输入 王五 的成绩(0-100):82
✅ 已录入:王五 - 82.0 分
请输入学生姓名(输入 q 结束录入):q
========================================
查询菜单
1. 查看全部成绩
2. 查看及格的学生(>=60)
3. 查看不及格的学生(<60)
4. 按姓名搜索
========================================
请选择查询方式(1-4):1
========================================
全部学生成绩
========================================
序号 姓名 成绩 等级
----------------------------------------
1 张三 95.0 优秀
2 李四 58.0 不及格
3 王五 82.0 良好
----------------------------------------
总人数:3 人
平均分:78.3
最高分:95.0
最低分:58.0
及格率:2/3(67%)
========================================
分步拆解:
-
数据结构设计:用列表
students存所有学生,每个学生是一个字典{"姓名": ..., "成绩": ...}。列表负责存"一堆",字典负责存"一个人的多个属性"——这是列表+字典组合的经典用法 -
while循环录入:while True无限循环,输入q时break跳出。成绩不合法时continue跳过本次循环,重新录入——这是第5章学过的循环控制 -
strip()清理输入:input(...).strip()去掉用户输入首尾可能多打的空格,这是本章学的字符串方法 -
查询菜单:用
if-elif-else处理4种查询方式。列表推导式[s for s in students if ...]是第6章列表知识的应用,按条件筛选数据 -
f-string格式化成绩单:f"{i:<6}{s['姓名']:<10}..."用<左对齐、数字控制宽度,让输出像表格一样整齐——这正是格式化输出的实际应用 -
统计信息:用
sum()、max()、min()配合列表推导式快速算出平均分、最高分、最低分。及格率用sum(1 for s in scores if s >= 60)统计及格人数,再算百分比
这个案例串联了第二部分全部知识:列表(存多人数据)、字典(存单人属性)、
for循环(遍历输出)、while循环(循环录入)、break/continue(循环控制)、条件判断(等级判定、菜单选择)、字符串方法(strip)、f-string格式化(成绩单对齐输出)。能独立写出来,说明第二部分已经完全掌握了。
七、常见报错速查表
| 报错信息 | 出现场景 | 原因 | 解决方法 |
|---|---|---|---|
TypeError: 'str' object does not support item assignment |
试图通过索引修改字符串 | 字符串不可变 | 用 replace() 或切片拼接生成新字符串 |
IndexError: string index out of range |
访问不存在的索引 | 索引超出字符串长度 | 检查索引范围,最大索引 = len(s) - 1 |
TypeError: can only concatenate str to str |
字符串和数字用 + 拼接 |
类型不兼容 | 用 str() 转换数字,或改用 f-string |
AttributeError: 'str' object has no attribute 'xxx' |
调用不存在的字符串方法 | 方法名拼写错误 | 查阅方法速览表,确认方法名正确 |
ValueError (split 场景) |
对 split 结果按索引取值越界 |
分隔符不匹配导致结果数量少于预期 | 先 print 查看 split 结果再取值 |
KeyError (format 场景) |
format 的 {} 数量与参数不匹配 |
占位符和参数个数对不上 | 检查 {} 个数与 format() 参数数量 |
九、本章小结
本章你掌握了字符串操作和格式化输出的完整体系:
- 字符串切片——
[起:止:步长],左闭右开,[::-1]反转字符串 - 8个常用方法——
upper/lower转大小写、strip去空白、replace替换、split拆分、join合并、find查找、count计数 - 三种格式化输出——
%格式化(能读懂)、format()方法(灵活复用)、f-string(日常首选) - 字符串不可变——所有方法都返回新字符串,不会修改原字符串
到本章为止,第二部分(循环与容器篇)全部学完。你已经能熟练使用列表、字典、for/while 循环、条件判断和字符串操作——这些是 Python 编程最常用的工具组合。
往期回顾:
零基础学 Python 第1章 | 全平台装环境 + VS Code 配置 + 第一个 Hello World
零基础学 Python 第2章 | print 输出 + 变量赋值 + input 交互输入
零基础学 Python 第3章 | 条件判断:if / elif / else
零基础学 Python 第 4 章 | for 循环与 range():让程序帮你重复干活
零基础学 Python 第 5 章 | while 循环与循环嵌套:让程序看着条件自己干活
零基础学 Python 第 6 章 | 元组与集合:不可变数据与自动去重
零基础学 Python 第7章 | 字典 dict:键值对存储
下一章预告:前面几章我们写了不少重复的代码,比如成绩判等级的逻辑在多个程序里都出现过。如果能把一段代码"打包"起来,起个名字,需要时直接调用,岂不是省事很多?下一章学习函数基础——def 定义函数、参数传递、返回值,让你的代码从"一整坨"变成"模块化积木"。
文末资源区
| 资源 | 说明 |
|---|---|
| Python 官方文档 - 字符串方法 | https://docs.python.org/3/library/stdtypes.html#string-methods |
| Python 官方文档 - 字符串格式化 | https://docs.python.org/3/library/string.html#formatstrings |
Python 官方文档 - f-string |
https://docs.python.org/3/reference/lexical_analysis.html#f-strings |
| Python 官方文档 - 切片 | https://docs.python.org/3/library/functions.html#slice |
| 本章完整源码 | chapter8_all.py(关注梅雅达编程笔记,评论领资料) |
每节课都配套课后练习题与完整源码。代码报错、看不懂知识点,可在评论区粘贴问题,逐一解答!
欢迎关注梅雅达编程笔记,持续分享Python零基础学习内容
更多推荐


所有评论(0)