这个观察其实很重要:str 字符串和 list 列表,都支持索引,都能用下标去取某个位置的内容,看起来确实很像。
但是它们有一个非常关键的区别:
字符串是不可变类型(immutable),列表是可变类型(mutable)。
这句话就是它们最核心的差别。
也就是说:
- 字符串里的某个字符,可以取出来看
- 但是不能直接改其中某一个位置
- 列表里的某个元素,不但可以看,还可以直接改
所以你会感觉它们“表面像”,但真正写代码时,行为差很多。
先看它们相同的地方
1. 都可以用索引取值
name = "hello"
nums = [10, 20, 30]
print(name[0])
print(nums[0])
输出:
h
10
这里说明:
"hello"的第 0 个位置是"h"[10, 20, 30]的第 0 个位置是10
也就是说,字符串和列表都属于“序列”,都可以按位置访问内容。
2. 都可以切片
name = "hello"
nums = [10, 20, 30, 40]
print(name[1:4])
print(nums[1:3])
输出:
ell
[20, 30]
说明:
- 字符串切片,得到的还是字符串
- 列表切片,得到的还是列表
3. 都可以用 for 循环遍历
name = "abc"
nums = [1, 2, 3]
for ch in name:
print(ch)
for x in nums:
print(x)
这也说明它们在“按顺序存放多个内容”这件事上很相似。
它们最关键的区别:能不能改
字符串不能这样改
name = "hello"
name[0] = "H"
这段代码会报错。
原因不是你索引写错了,而是:
字符串一旦创建好,里面的字符就不能原地修改。
你只能“重新生成一个新字符串”,不能直接把原来的某一个位置改掉。
比如想把 "hello" 变成 "Hello",要这样写:
name = "hello"
name = "H" + name[1:]
print(name)
输出:
Hello
这里不是“改原字符串里面的第 0 个字符”,而是:
- 取出
"H" - 再取出原字符串后面的
"ello" - 拼成一个新的字符串
"Hello" - 再让变量
name指向这个新字符串
列表可以直接改
nums = [10, 20, 30]
nums[0] = 99
print(nums)
输出:
[99, 20, 30]
这说明列表里面的元素,是可以直接修改的。
所以你可以把列表理解成:
一个可以随时增删改的“可变容器”。
用最直白的话区分一下
你可以先这样记:
- 字符串:更像“一整段文字”,通常用来表示文本内容
- 列表:更像“一个盒子,里面放很多东西”,通常用来存多个数据
虽然字符串看起来也像“装了很多字符”,但 Python 把它当作“文本”来处理,所以它不允许你随便改某个字符。
而列表本来就是为了存多个元素并方便修改而设计的,所以它能改。
它们合并的时候也有相似点,但结果不同
字符串合并
a = "hello"
b = "world"
print(a + b)
输出:
helloworld
如果想中间有空格:
print(a + " " + b)
输出:
hello world
这里的 + 是字符串拼接。
列表合并
a = [1, 2]
b = [3, 4]
print(a + b)
输出:
[1, 2, 3, 4]
这里的 + 是把两个列表连接起来,得到一个新的列表。
所以虽然都能用 +,但是含义要分清:
- 字符串的
+:拼文本 - 列表的
+:拼元素序列
print 直接打印时,该怎么操作
这个部分很基础,但非常重要。
1. 直接打印字符串
name = "hello"
print(name)
输出:
hello
字符串直接打印,就是把文字显示出来。
2. 直接打印列表
nums = [10, 20, 30]
print(nums)
输出:
[10, 20, 30]
这里你会发现,列表打印出来会带中括号,因为 Python 在告诉你:这是一个列表。
如果我不想让列表带中括号打印,怎么办
这是初学者很容易碰到的问题。
比如:
words = ["a", "b", "c"]
print(words)
输出是:
['a', 'b', 'c']
如果你想打印成:
a b c
可以用下面的方法。
方法1:用 for 循环逐个打印
words = ["a", "b", "c"]
for w in words:
print(w)
输出:
a
b
c
这是“一行一个”。
方法2:用 join() 把字符串列表拼起来
words = ["a", "b", "c"]
print(" ".join(words))
输出:
a b c
这里要注意:
join() 只能拼接“字符串列表”。
也就是说,下面这种可以:
words = ["hello", "python", "world"]
print("-".join(words))
输出:
hello-python-world
如果列表里是数字,不能直接 join
比如:
nums = [1, 2, 3]
print(" ".join(nums))
这会报错。
因为 join() 要求列表里的每个元素都必须是字符串,但这里是整数。
要先转成字符串:
nums = [1, 2, 3]
for n in nums:
print(n)
或者以后学得再多一点时,再用更方便的转换方法。
对于初学阶段,你先记住:
- 列表里如果是数字,最稳妥的方法是
for循环打印 - 列表里如果本来就是字符串,可以用
join()
从思路到代码:怎么判断该用字符串还是列表
写代码时,可以先问自己一句话:
我现在处理的是“一段文字”,还是“多个独立的数据项”?
如果是一段文字,用字符串
例如:
- 姓名
- 一句话
- 一个单词
- 用户输入的一行文本
name = "Tom"
sentence = "I like Python"
如果是多个独立数据,用列表
例如:
- 多个成绩
- 多个名字
- 多个商品
- 多个数字
scores = [90, 85, 100]
names = ["Tom", "Jack", "Lucy"]
一个非常典型的对比例子
字符串
text = "abc"
print(text[1])
输出:
b
这里取出来的是一个字符。
但是不能改:
text[1] = "x"
不行。
列表
letters = ["a", "b", "c"]
print(letters[1])
输出:
b
而且可以改:
letters[1] = "x"
print(letters)
输出:
['a', 'x', 'c']
所以你可以看到:
- 字符串像“不能拆开改的文本”
- 列表像“可以拆开改的元素集合”
再补一个容易混淆的点:字符串中的每个字符也是字符串
这个地方初学者很容易忽略。
text = "hello"
print(text[0])
print(type(text[0]))
输出:
h
<class 'str'>
也就是说:
text[0] 取出来的不是“字符类型”,而是一个长度为 1 的字符串。
Python 里没有单独的“字符类型”,单个字符本质上还是字符串。
常见错误与易混点
1. 以为字符串既然能索引,就一定能修改
这是最常见误区。
能索引,只说明你能“访问它的某个位置”,不代表你能改。
2. 把列表和字符串的打印效果混为一谈
print("hello")
print(["h", "e", "l", "l", "o"])
输出完全不一样:
hello
['h', 'e', 'l', 'l', 'o']
因为一个是字符串,一个是列表。
3. 对数字列表直接使用 join()
nums = [1, 2, 3]
print(" ".join(nums))
这是错误的。
因为 join() 只能连接字符串。
4. 误以为字符串加法和列表加法是同一种意思
虽然都写 +,但本质不一样:
"ab" + "cd"得到"abcd"[1, 2] + [3, 4]得到[1, 2, 3, 4]
形式一样,操作对象不同,结果也不同。
本节小结
你可以先把核心区别记成下面这几句话:
| 对比点 | 字符串 str | 列表 list |
|---|---|---|
| 是否支持索引 | 支持 | 支持 |
| 是否支持切片 | 支持 | 支持 |
| 是否能遍历 | 能 | 能 |
| 是否能直接修改某个位置 | 不能 | 能 |
| 主要用途 | 表示文本 | 存放多个元素 |
直接 print() 的效果 | 直接显示文本 | 显示整个列表结构 |
最重要的一句是:
字符串是不可变的,列表是可变的。
最小可运行例子
你可以直接运行下面这段,感受一下区别:
text = "hello"
nums = [1, 2, 3]
print("字符串第0个元素:", text[0])
print("列表第0个元素:", nums[0])
nums[0] = 100
print("修改后的列表:", nums)
print("直接打印字符串:", text)
print("直接打印列表:", nums)
输出大概是:
字符串第0个元素: h
列表第0个元素: 1
修改后的列表: [100, 2, 3]
直接打印字符串: hello
直接打印列表: [100, 2, 3]
练习
题目
写一段程序,完成下面几件事:
- 定义一个字符串
"python" - 打印它的第 2 个字符
- 定义一个列表
[10, 20, 30] - 把列表中第 2 个元素改成
99 - 打印修改后的列表
提示
- 索引从
0开始 - 第 2 个字符,其实索引是
1 - 列表可以直接写
列表名[索引] = 新值



