第1章 1.3 字符串与 f-string 格式化

上回咱们聊了变量和基本数据类型,其中字符串(str)算是最常用的一个——毕竟程序嘛,就是处理文本的艺术。但上一章只提到了字符串"有这玩意儿",没来得及细说。

这一章咱们要把字符串彻底吃透,特别是 f-string 这个神器。学完之后,你处理文本就像用筷子夹菜一样熟练。


🎯 开场 3 分钟:为什么要学这个?

你有没有遇到过这些情况:

  • 写了个程序,想把变量插进文字里,结果一堆 + 号拼来拼去,自己都看晕了
  • 字符串里有引号或者换行符,程序就报错了
  • 从网上抓下来的数据,想按格式输出成报告,憋了半天写不出来

这些问题,学完这章全解决


🧱 基础 25 分钟:核心概念

1.3.1 字符串的创建:引号是它的边界

字符串说白了就是用引号包起来的一串字符

# 三种创建方式,效果一样
name = "小明"           # 双引号
age = '18'             # 单引号(注意!这是字符串不是数字)
intro = """我是小明,
今年18岁"""            # 三引号,可以换行

说白了:引号就是字符串的"边界线",告诉 Python 从哪开始、到哪结束。

1.3.2 转义字符:字符串里的"特种兵"

有时候字符串里要放特殊字符,比如换行、Tab、引号本身。这时候就需要 转义字符 \,相当于给字符"化装"。

# \n 是换行,\t 是Tab,\' 是单引号本身
dialog = "他说:\"今天天气不错\"\n然后转身走了"
print(dialog)

输出:

他说:"今天天气不错"
然后转身走了

为什么要用:没有转义字符,你就没法在字符串里放引号——Python 会以为引号是字符串的边界。

小技巧:如果不想记转义字符,在字符串前面加 r,变成原始字符串(raw string):

path = r"C:\Users\小明\Desktop"  # 不用写双反斜杠
print(path)

1.3.3 字符串切片:文本的"切肉刀"

字符串像一根绳子,可以切成若干段。语法是 字符串[起始:结束:步长]

text = "Hello World"
print(text[0])      # H - 第1个字符
print(text[0:5])    # Hello - 第1到第5个字符
print(text[6:])     # World - 第7个到最后
print(text[-1])     # d - 倒数第1个
print(text[::-1])   # dlroW olleH - 倒序

生活类比:切片就像切面包,你告诉老板"我要从第几片到第几片",他就给你切好。

配图1 - 配图1

1.3.4 字符串常用方法:它的"内置技能"

字符串自带很多方法(函数),直接调用就行。记不住没关系,用到时查就行。

s = "  Hello Python!  "

print(s.strip())        # Hello Python! - 去掉首尾空格
print(s.lower())        #   hello python!  - 全部小写
print(s.upper())        #   HELLO PYTHON!  - 全部大写
print(s.replace("Python", "World"))  #   Hello World!  - 替换
print(s.split(" "))     # ['', '', 'Hello', 'Python!', '', ''] - 分割成列表
print(len(s))           # 18 - 长度(这是函数不是方法)

为什么要用方法:不用自己写代码遍历字符,Python 已经帮你封装好了。

1.3.5 f-string:格式化界的"瑞士军刀"

终于到重头戏了!f-string 是 Python 3.6 引入的格式化神器,f 是 format(格式化)的意思。

核心思想:在字符串前面加个 f,里面用 {} 包住变量,Python 会自动把变量值"塞进去"。

name = "小明"
age = 18
height = 1.75

# 以前要这样写(麻烦)
intro_old = "我叫" + name + ",今年" + str(age) + "岁"

# 现在用 f-string(清爽)
intro = f"我叫{name},今年{age}岁,身高{height}米"
print(intro)

输出:

我叫小明,今年18岁,身高1.75米

生活类比:f-string 就像填空题的答题卡,你提前画好 {姓名} {年龄} 的空,考试时直接往里填。

1.3.6 f-string 表达式插值:{} 里能放算式

{} 里不只能放变量名,放表达式也行

a = 10
b = 3

print(f"{a} + {b} = {a + b}")        # 10 + 3 = 13
print(f"{a} * {b} = {a * b}")        # 10 * 3 = 30
print(f"{a} / {b} = {a / b:.2f}")    # 10 / 3 = 3.33(保留2位小数)
print(f"{a} 的平方是 {a**2}")         # 10 的平方是 100

注意{a / b:.2f} 这个 :2f 是格式化语法,意思是"保留2位小数"。

配图2 - 配图2

1.3.7 format() 方法:老派写法了解一下

在 f-string 出现之前,人们用 .format() 方法。虽然现在 f-string 更简洁,但看懂旧代码也很重要。

name = "小明"
score = 95

# format() 的三种姿势
print("我叫{},成绩是{}分".format(name, score))
print("我叫{0},成绩是{1}分,{0}加油!".format(name, score))
print("我叫{n},成绩是{s}分".format(n=name, s=score))

建议:新代码直接用 f-string,老代码认识就行。


🔥 实战 35 分钟:3 个递进的小项目

项目 1:个人信息卡(5 分钟)

需求:把用户的信息格式化成一张"名片"输出。

# 项目1:个人信息卡
name = "张小明"
age = 28
job = "软件工程师"
city = "北京"
salary = 25000

# 用 f-string 拼接
card = f"""
==============
姓名:{name}
年龄:{age}
职业:{job}
城市:{city}
月薪:{salary}元
==============
"""
print(card)

预期输出

==============
姓名:张小明
年龄:28
职业:软件工程师
城市:北京
月薪:25000元
==============

一句话解释:f-string 让多行文本和变量混排变得超级简单。


项目 2:批量处理通讯录数据(15 分钟)

需求:从 CSV 格式的通讯录里读取数据,格式化输出每个人的信息。

# 项目2:批量处理通讯录
# 模拟 CSV 数据(实际可以用 open('file.csv') 读取)
contacts_csv = """姓名,电话,邮箱
张小明,13800138000,zhang@email.com
李华,13900139000,lihua@email.com
王芳,13700137000,wang@email.com"""

# 解析 CSV(简单版,不处理引号等复杂情况)
lines = contacts_csv.strip().split('\n')
headers = lines[0].split(',')
people = []
for line in lines[1:]:
values = line.split(',')
person = dict(zip(headers, values))
people.append(person)

# 格式化输出每个人信息
print("=== 通讯录(格式化后)===")
for p in people:
print(f"姓名:{p['姓名']}")
print(f"电话:{p['电话']}")
print(f"邮箱:{p['邮箱']}")
print("-" * 20)

预期输出

=== 通讯录(格式化后)===
姓名:张小明
电话:13800138000
邮箱:zhang@email.com
--------------------
姓名:李华
电话:13900139000
邮箱:lihua@email.com
--------------------
姓名:王芳
电话:13700137000
邮箱:wang@email.com
--------------------

一句话解释:用 split() 把 CSV 拆成列表,再转成字典,用 f-string 格式化输出。


项目 3:待办清单小工具(15 分钟)

需求:做一个命令行待办清单,支持添加、查看、标记完成功能。

# 项目3:待办清单小工具
todos = []

def show_menu():
print(f"""
=== 待办清单 ===
当前有 {len(todos)} 项待办:
""")
if not todos:
    print("(空)")
else:
    for i, todo in enumerate(todos, 1):
        status = "✓" if todo["done"] else "○"
        priority = "🔥" if todo["priority"] == "高" else "  "
        print(f"{i}. [{status}] {priority}{todo['task']}")
print()

def add_task(task, priority="中"):
todos.append({"task": task, "priority": priority, "done": False})
print(f"✅ 已添加:{task}(优先级:{priority})")

def complete_task(index):
if 0 < index <= len(todos):
    todos[index-1]["done"] = True
    print(f"🎉 已完成:{todos[index-1]['task']}")
else:
    print("❌ 无效序号")

# 演示用法
show_menu()
add_task("写周报", priority="高")
add_task("回复邮件", priority="中")
add_task("整理桌面", priority="低")
show_menu()
complete_task(1)
show_menu()

预期输出

=== 待办清单 ===
当前有 0 项待办:

(空)

✅ 已添加:写周报(优先级:高)
✅ 已添加:回复邮件(优先级:中)
✅ 已添加:整理桌面(优先级:低)

=== 待办清单 ===
当前有 3 项待办:

1. [○] 🔥 写周报
2. [○]    回复邮件
3. [○]    整理桌面

🎉 已完成:写周报

=== 待办清单 ===
当前有 3 项待办:

1. [✓] 🔥 写周报
2. [○]    回复邮件
3. [○]    整理桌面

一句话解释:用字典存储每条待办的状态,f-string 把数据格式化成漂亮的输出。


💪 进阶 20 分钟:常见坑 + 性能小贴士

坑 1:引号嵌套搞混

❌ 错误写法:

# 这行不通!
s = "他说:"你好""

✅ 正确写法:

s = '他说:"你好"'           # 外双内单
s = "他说:\"你好\""         # 转义
s = f'他说:"{"你好"}"'      # f-string 混合

坑 2:f-string 里误用单引号包字符串

❌ 错误写法:

name = "小明"
s = f'你好,{name},'说'什么?'  # 单引号嵌套会乱

✅ 正确写法:

s = f'你好,{name},{"说"}什么?'  # 内部用双引号
s = f"你好,{name},'说'什么?"   # 外部用双引号

坑 3:误把数字和字符串直接拼接

❌ 错误写法:

age = 18
s = "年龄:" + age   # TypeError!

✅ 正确写法:

s = f"年龄:{age}"      # f-string 自动转
s = "年龄:" + str(age) # 手动转

坑 4:转义字符没生效

❌ 错误写法:

path = "C:\Users\王五\Desktop"  # \U 会被识别成转义序列

✅ 正确写法:

path = r"C:\Users\王五\Desktop"  # 加 r 保持原始
path = "C:\\Users\\王五\\Desktop" # 双重转义

坑 5:切片越界不报错但结果不对

❌ 错误写法:

s = "Hello"
print(s[0:10])  # 不报错,但新手容易困惑

✅ 正确写法:

s = "Hello"
print(s[0:5])   # 明确范围
print(s[6:10])  # 返回空字符串,不会报错

性能小贴士:频繁拼接用 join

# 不好:每次 + 都会创建新字符串
result = ""
for i in range(1000):
result += str(i)

# 好:一次性拼接
result = "".join(str(i) for i in range(1000))

调试技巧:善用 f-string 打印中间变量

# 快速查看变量值(调试专用)
x = 10
y = 3
print(f"DEBUG: x={x}, y={y}, x/y={x/y:.2f}")

✏️ 练习题

练习 1(2 分钟):基础变形

  • 输入:给定变量 name = "小红" age = 16
  • 预期输出小红今年16岁了
  • 提示:用 f-string,把变量塞进 {}

练习 2(2 分钟):加个判断

  • 输入:沿用练习 1 的变量,外加 has_gift = True
  • 预期输出:如果 has_gift 为 True,输出 小红今年16岁了,收到礼物啦!,否则输出 小红今年16岁了
  • 提示:在 f-string 里用 {变量 if 条件 else 变量} 三元表达式

练习 3(3 分钟):处理新数据

  • 输入data = "苹果,5,3.5|香蕉,3,2.8|橙子,8,4.2"(格式:水果,数量,单价)
  • 预期输出:列出每种水果的"水果名: 数量×单价=小计",如 苹果: 5×3.5=17.5元
  • 提示:先用 split("|") 分割,再用 split(",") 分割每项

练习 4(5 分钟):串联项目

  • 输入:把项目 2 的 CSV 数据改成 JSON 格式 {"name": "张三", "score": 88}
  • 预期输出:格式化输出 张三同学考了88分,评级为A
  • 90分以上是A,80-89是B,60-79是C,60以下D
  • 提示:把项目 2 的解析逻辑和项目 3 的条件判断组合起来

练习 5(5 分钟):报错分析

  • 输入:以下代码为什么会报错?
name = "小明"
print(f'你好,{name},老师说:"今天要写{f-string}')
  • 预期输出:说明错误原因并给出修正后的代码
  • 提示:检查引号嵌套

作业:做一个「文本数据清洗工具」

需求描述:写一个工具,读取一批原始文本数据,进行清洗和格式化,输出整齐的报告。

功能点
1. 能读取多行文本(可以硬编码在代码里)
2. 去除空格、转换大小写、统计字符数
3. 按指定格式输出(如:编号 | 原文本 | 清洗后 | 字数)

加分项
1. 支持从列表里处理多条数据
2. 把结果导出成带边框的表格形式

验收标准
- 能跑起来(复制进 Python 文件直接运行)
- 输出符合预期格式
- 代码有注释(每段功能用 # 说明)

提交方式:评论区贴代码或 GitHub 链接


📚 总结 + 资源

这一章学了 3 个核心点:
- 字符串切片:用 [start:end] 切分文本
- 转义字符:用 \ 处理特殊字符
- f-string:用 f"你好,{名字}" 格式化输出

延伸资源
- 官方文档:https://docs.python.org/3/library/string.html
- 书籍:《Python编程:从入门到实践》第 4 章
- 视频:B 站小甲鱼《零基础学 Python》第 15 讲

互动钩子:你在做数据分析或者爬虫的时候,字符串处理有没有遇到过什么奇葩问题?评论区聊聊,老粉优先回复!


下一章我们要学「输入输出与运算符」,到时候你就能做出真正的交互式程序了——不再是只能 print 固定内容,而是能读取用户输入然后做计算。期待一下吧!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。