上周末你考完第一次周测,已经能独立跑通几个小程序了。从今天起,我们正式进入 Python 的数据世界,第一站是字符串。
字符串这东西你其实天天见:微信里发给朋友的话、程序里弹出来的"请输入姓名"、网页上显示的标题,全是字符串。而程序最常干的活,也就是处理文字——把用户输入的名字转成大写、把一段话里的词替换掉、把一句话按空格拆成一个个单词。这些操作 Python 都有现成的工具,今天就把它们一个个用熟。
学完今天,你就有了一个"文字加工厂":取一个字、截一段、改一改、拆一拆,随手就能干。
字符串就是带引号的一串文字
在 Python 里,用引号包起来的一串字符就叫字符串(英文 str)。单引号、双引号都行:
name = "小明" # 双引号包起来的文字
city = '北京' # 单引号也可以
year = "2025" # 注意:这是字符串,不是数字
print(name, city, year) # 小明 北京 2025
print(type(name)) # <class 'str'>,说明它是字符串类型
先看一个最容易搞混的地方:数字加上引号,就不是数字了。
s1 = "你好,世界"
s2 = 'Hello'
s3 = "123" # 加引号就是字符串
s4 = 123 # 不加引号才是数字
print(type(s1)) # <class 'str'>
print(type(s3)) # <class 'str'>
print(type(s4)) # <class 'int'>
print(s1 + s2) # 你好,世界Hello(字符串拼接,后面讲)
输出长这样:
<class 'str'>
<class 'str'>
<class 'int'>
你好,世界Hello
123 是数字,能拿去做加减法;"123" 是三个字符组成的文字,拿去加减法会直接报错。这个区分以后会反复遇到,现在就记牢。
写字符串还有几条规矩,都是新手常踩的:
- 引号必须成对:用
"开头就得用"结尾,"abc'这样混着写,直接报SyntaxError。 - 字符串里想写引号,外层用双引号、内层用单引号,比如
"他说'你好'",两边不冲突。
字符串里的每个字符——字母、数字、空格、标点——都有自己固定的位置,就像排队的人都有自己站的位子。下面我们就给这些位子编号。
给每个字符编上号:索引
字符串里每个字符都有编号,用 字符串[编号] 就能取出那一个字符。这个编号叫索引(index),两条规则必须记牢:
| 规则 | 说明 | 例子 |
|---|---|---|
| 正数索引 | 从 0 开始数,第 1 个字符是 0 | "abc"[0] 是 a |
| 负数索引 | 从 -1 开始往左数,最后一个字符是 -1 | "abc"[-1] 是 c |
s = "Python"
# P y t h o n
# 0 1 2 3 4 5 正数下标
# -6-5-4-3-2-1 负数下标
print(s[0]) # P(第 1 个字符)
print(s[3]) # h(第 4 个字符)
print(s[5]) # n(最后一个字符)
print(s[-1]) # n(负数从右往左数,-1 就是最后一个)
print(s[-2]) # o
输出:
P
h
n
n
o
这里最容易错的就是"下标从 0 开始":"abc"[1] 是 b,不是 a。第一次写错很正常,多取几次就习惯了。负数下标从 -1 开始,没有"负 0"这种说法——-0 就等于 0,也就是第一个字符。
拿真实场景练一下,比如 11 位手机号:
phone = "13800138000"
# 下标: 0 1 2 3 4 5 6 7 8 9 10
print(phone[0]) # 1(第 1 位)
print(phone[2]) # 8(第 3 位)
print(phone[-1]) # 0(最后 1 位)
print(len(phone)) # 11(一共 11 个字符,len 是长度)
输出:
1
8
0
11
len(字符串) 返回字符个数。它还是排查越界报错的好帮手:下标最多到 len - 1,取 s[len(s)] 会报 IndexError: string index out of range。拿不准长度时,先 len() 一下再取。
取出中间的一段:切片
索引取一个字符,切片取一段。写法是 字符串[开始:结束],把开始和结束的位置填进去就行。
切片只有一条铁律:含头不含尾——开始位置取得到,结束位置取不到。这跟 range(1, 6) 产出 1~5 是同一个道理。
s = "Hello Python"
print(s[0:5]) # Hello(第 0 到第 4 个,第 5 个不取)
print(s[6:12]) # Python(第 6 到第 11 个)
print(s[6:]) # Python(省略结束,表示一直取到末尾)
print(s[:5]) # Hello(省略开始,表示从 0 开始)
print(s[:]) # Hello Python(都不写,就是复制整个字符串)
输出:
Hello
Python
Python
Hello
Hello Python
[开始:结束] 还能再加第三个位置——步长,隔几个取一个:
s = "0123456789"
print(s[2:6]) # 2345(含头不含尾)
print(s[-4:]) # 6789(从倒数第 4 个取到末尾)
print(s[0:10:2]) # 02468(步长 2,隔一个取一个)
print(s[::-1]) # 9876543210(步长 -1,整个倒过来!)
输出:
2345
6789
02468
9876543210
[::-1] 是"从后往前全取",字符串倒序就靠它。两个容易混的地方:
- 切片的结束位置取不到:
"Hello"[0:4]结果是Hell,不是Hello。 - 切片越界不报错:
"abc"[0:99]返回"abc"。这一点和索引正好相反——索引越界报错,切片越界不报错。
加工文字的小工具:方法
Python 给字符串配了一堆现成的小工具,叫方法(method),写法是 字符串.方法名()。今天必须会 6 个,个个都常用:
| 方法 | 作用 | 例子 | 结果 |
|---|---|---|---|
upper() |
全部变大写 | "abc".upper() |
ABC |
lower() |
全部变小写 | "ABC".lower() |
abc |
strip() |
去掉首尾空格 | " hi ".strip() |
hi |
replace(a, b) |
把 a 换成 b | "Hi Tom".replace("Tom", "AI") |
Hi AI |
split() |
按空格拆成单词列表 | "a b c".split() |
['a', 'b', 'c'] |
count(x) |
数 x 出现几次 | "banana".count("a") |
3 |
一次看个够:
s = " Hello Python "
print(s.upper()) # HELLO PYTHON (变大写)
print(s.lower()) # hello python (变小写)
print(s.strip()) # Hello Python(首尾空格去掉)
print(s.replace("Python", "AI")) # Hello AI (换词)
print(s.split()) # ['Hello', 'Python'](按空格拆成列表)
print("banana".count("a")) # 3(a 出现了 3 次)
输出:
HELLO PYTHON
hello python
Hello Python
Hello AI
['Hello', 'Python']
3
split() 拆出来的 ['Hello', 'Python'] 是个列表——明天的课就学它,今天先认识个脸。
这里有个特别反直觉的坑:upper() 之类的方法不会改掉原字符串,而是返回一个新字符串。看这段:
s = "hello"
s.upper() # 这句话执行完,结果丢了
print(s) # hello(s 还是小写,没变!)
s = s.upper() # 把结果存回去才对
print(s) # HELLO
输出:
hello
HELLO
原因是 Python 里字符串一旦创建就不能改(术语叫不可变)。所有加工方法都是返回一份新的,原字符串原封不动。想保留加工结果,就必须赋值接住:s = s.upper()。
新手常在这三个地方翻车:
- 忘写括号:
s.upper不报错,但打印出来是奇怪的东西——方法是函数,必须带()。 - 忘了接住结果:
s.upper()之后打印s,发现没变,就是上面说的原因。 strip()只去掉首尾的空格,中间的空格不动:"a b".strip()还是"a b"。
把几段文字拼成一句:拼接和 f-string
程序里经常要把几段文字拼成一句话输出。有两种拼法:加号拼接,和 f-string(推荐)。
name = "小明"
age = 18
# 方式一:加号拼接(数字不能直接拼,要先转字符串)
print("我叫" + name + ",今年" + str(age) + "岁")
# 方式二:f-string(推荐,不用管类型)
print(f"我叫{name},今年{age}岁")
输出:
我叫小明,今年18岁
我叫小明,今年18岁
f-string 就是在字符串前面加个 f,把要插入的内容用 {} 包起来,像填空一样。第 2 周见过它,今天开始把它当主力用。
加号拼接有个经典报错:字符串和数字不能直接 +,"我" + 18 会报 TypeError。要么 str(18) 转一下,要么直接用 f-string——这也是推荐 f-string 的原因,它不用管类型。
加工方法和拼接经常搭档着用:
word = " python "
word = word.strip() # 去掉空格 → python
word = word.upper() # 变大写 → PYTHON
print(f"我最喜欢的语言是:{word}")
输出:
我最喜欢的语言是:PYTHON
f-string 还有两个小讲究:{} 里放变量名,不要加引号——f"{'name'}" 输出的就是 name 这几个字母,不是变量的值;整个字符串要用引号包起来,且和内部的引号不冲突。
小实战:数一数一句话有几个单词
把今天学的串起来做一个真实小功能:输入一句话,输出这句话有几个单词。思路分三步:
input()收用户输入的一句话- 用
split()按空格拆成一个单词列表 - 用
len()数列表里有几个元素,就是几个单词
text = input("请输入一句话:")
words = text.split() # 按空格拆成单词列表
print(words) # 看看拆成了什么
print(f"一共有 {len(words)} 个单词")
假设输入 python is fun,输出:
请输入一句话:python is fun
['python', 'is', 'fun']
一共有 3 个单词
两个提醒:split() 不传参数时按"任意连续空白"拆分,比 split(" ") 更稳——用户多敲了几个空格也拆不错;统计要用 len(words)(单词个数),别写成 len(text)(那是字符个数)。用户输入两个空格或一个中文空格时,split() 可能拆出空字符串,统计就不准——这个坑留到明天的进阶练习,我们拉上 AI 一起解决。
随堂练习
练习一:把这句话加工一遍
对字符串 "python is fun" 依次做 4 件事:取第 0 个字符、取前 6 个字符、全部变大写、把 fun 换成 cool。
提示:第 0 个字符用索引 s[0];前 6 个用切片 s[:6];大写用 upper();换词用 replace()。
练习二:手机号打码
输入一个 11 位手机号,输出它的前 3 位和最后 4 位,中间用 **** 代替。比如输入 13800138000,输出 138****8000。
提示:前 3 位用 phone[:3],后 4 位用 phone[-4:],最后用 f-string 拼起来。
进阶题(可选):数单词
输入一句话,用 split() 拆开,输出单词个数;再升级一步:把每个单词单独打印出来(用第 2 周学的 for 循环遍历)。
写不出来时,让 AI 搭把手
场景:手机号打码这类"截取 + 拼接"的题目写不出来时
提示词:
我是 Python 初学者,正在学字符串切片。请帮我写一个程序:
输入一个 11 位手机号,输出前 3 位和后 4 位,中间用 **** 代替。
要求用切片实现,代码加注释,每行注释解释在干什么。
场景:想对字符串做某种加工但不知道用什么方法
提示词:
我在学 Python 字符串。我有一个字符串变量 s,想要去掉它首尾的空格、
把所有字母变小写、再把里面的 "old" 替换成 "new"。
请告诉我分别用什么方法,并给我一段完整的示例代码。
常见报错速查
| 报错信息 | 什么意思 | 怎么办 |
|---|---|---|
IndexError: string index out of range |
下标超了,取了一个不存在的字符 | 用 len() 确认长度,下标范围是 0 到 len-1 |
TypeError: can only concatenate str (not "int") to str |
字符串和数字不能直接 + |
用 str(数字) 转换,或直接改用 f-string |
SyntaxError: EOL while scanning string literal |
引号不配对 / 引号里换行了 | 检查引号是否成对,字符串别跨行 |
| 打印出来没变化 | 方法返回了新字符串但没保存 | 赋值接住:s = s.upper() |
收个尾
今天的内容概括成一句话:字符串是一串带引号的文字,索引和切片让你能"取",六个方法让你能"改",f-string 让你能"拼",split + len 让你能"数"。最要紧的那句别忘了——字符串不可变,加工结果要赋值接住。
明天学列表,字符串的"大号兄弟"。今天 split() 拆出来的 ['python', 'is', 'fun'] 就是一个列表,明天我们会学怎么往里面加东西、删东西、改东西,还要写一个购物车小程序。