Python 字符串完全指南(系统+详细)

字符串是 Python 中最常用的不可变序列类型,用于表示文本数据。本指南从基础到进阶,覆盖字符串的核心知识,包含语法、操作、方法、格式化、编码等内容,适合Python初学者系统学习。

一、字符串的定义与创建

字符串是由单个字符组成的有序集合,字符可以是字母、数字、符号、中文等 Unicode 字符。Python 中创建字符串的方式灵活多样,核心规则是用引号包裹

1. 基本创建方式(3种引号)

  • 单引号 ' ':适合包含双引号的字符串(无需转义)
  • 双引号 " ":适合包含单引号的字符串(无需转义)
  • 三引号 ''' '''""" """:支持多行字符串、保留格式(如换行、缩进),也可作为注释(但非官方推荐注释方式)
# 1. 单引号
str1 = 'Hello Python'
str2 = 'He said: "Python is easy"'  # 包含双引号,无需转义

# 2. 双引号
str3 = "Hello Python"
str4 = "I'm learning Python"  # 包含单引号,无需转义

# 3. 三引号(多行字符串)
str5 = '''第一行
第二行
第三行'''  # 保留换行符\n
str6 = """Python 字符串
支持 Unicode,比如中文、日文:こんにちは"""

# 4. 空字符串(长度为0)
empty_str = ""  # 或 ''、''''''
print(len(empty_str))  # 输出:0

2. 转义字符(处理特殊字符)

当需要在字符串中包含无法直接输入的字符(如换行、制表符)或与引号冲突的字符时,使用 \ 作为转义符。

转义字符含义示例输出结果
\n换行print("a\nb")a
b
\t制表符(Tab,4个空格)print("a\tb")a b
\\输出反斜杠 \print("a\\b")a\b
\'输出单引号 'print('I\'m Tom')I’m Tom
\"输出双引号 "print("He said \"Hi\"")He said “Hi”
\r回车(覆盖当前行)print("abc\r123")123
\uXXXXUnicode 字符(4位十六进制)print("\u4e2d")
原始字符串(禁用转义)

在字符串前加 rR,表示原始字符串\ 不再是转义符(常用于文件路径、正则表达式):

# 普通字符串(\n 被转义为换行)
print("C:\new\test.txt")  # 输出混乱(\n 换行)

# 原始字符串(\ 不转义)
print(r"C:\new\test.txt")  # 输出:C:\new\test.txt
print(R"He said: \"Hi\"")  # 输出:He said: \"Hi\"(\ 保留)

3. Unicode 支持(多语言字符)

Python 3 的字符串默认是 Unicode 编码,可直接包含任意语言的字符,无需额外处理:

# 中文、日文、特殊符号均可直接使用
str_unicode = "中文 Python 🐍 日本語 한국어"
print(str_unicode)  # 正常输出所有字符
print(len(str_unicode))  # 输出:15(每个 Unicode 字符算1个长度)

二、字符串的核心属性:不可变性

Python 字符串是不可变对象——创建后无法直接修改单个字符,只能通过「创建新字符串」来实现“修改”效果。

s = "hello"
# 错误:试图修改第0个字符(会报错 TypeError)
# s[0] = "H"

# 正确方式:通过拼接/切片创建新字符串
s_new = "H" + s[1:]  # 拼接 + 切片
print(s_new)  # 输出:Hello

# 原字符串并未改变
print(s)  # 输出:hello

❌ 常见误区:试图通过索引赋值修改字符串,会直接抛出 TypeError

三、字符串的访问:索引与切片

字符串是有序序列,每个字符都有唯一的索引(位置编号),可通过索引访问单个字符,通过切片获取子字符串。

1. 索引(访问单个字符)

  • 正向索引:从左到右,起始为 0(第一个字符)
  • 反向索引:从右到左,起始为 -1(最后一个字符)

语法:字符串[索引值]

s = "Python"
# 字符串长度:len(s) = 6,正向索引 0~5,反向索引 -1~-6

print(s[0])   # 正向:第一个字符 → 'P'
print(s[3])   # 正向:第四个字符 → 'h'
print(s[-1])  # 反向:最后一个字符 → 'n'
print(s[-3])  # 反向:倒数第三个字符 → 'h'

# 错误:索引越界(超出 0~len(s)-1 范围)
# print(s[6])   # IndexError: string index out of range
# print(s[-7])  # IndexError: string index out of range

2. 切片(获取子字符串)

切片用于截取字符串的一部分,返回新字符串(不改变原字符串)。

语法:字符串[start:end:step]
  • start:起始索引(包含,默认 0
  • end:结束索引(不包含,默认 len(字符串)
  • step:步长(每次跳过的字符数,默认 1step>0 正向截取,step<0 反向截取)
常见用法示例
s = "abcdefghij"  # 索引 0-9(正向),-10~-1(反向)

# 1. 基础切片(start:end)
print(s[2:5])   # 从索引2到4(不包含5)→ 'cde'
print(s[0:3])   # 从开头到索引2 → 'abc'(等价于 s[:3])
print(s[7:])    # 从索引7到结尾 → 'hij'
print(s[:])     # 复制整个字符串 → 'abcdefghij'

# 2. 步长切片(start:end:step)
print(s[0:8:2])  # 步长2:0→2→4→6 → 'aceg'
print(s[::3])    # 从开头到结尾,步长3 → 'adgj'
print(s[::-1])   # 步长-1:反向截取(反转字符串)→ 'jihgfedcba'
print(s[8:3:-1]) # 反向从索引8到4 → 'jihgf'

# 3. 负数索引切片
print(s[-5:-2])  # 从倒数第5到倒数第3 → 'fgh'
print(s[-3:])    # 倒数3个字符 → 'hij'

✅ 切片的核心特点:

  • 左闭右开(包含 start,不包含 end)
  • 索引越界不报错(自动忽略超出范围的部分):s[100:200]''(空字符串)
  • 始终返回新字符串(原字符串不变)

四、字符串的基础操作(拼接、重复、判断等)

Python 提供了简洁的运算符,用于字符串的常见操作。

1. 拼接(+

将两个或多个字符串合并为一个新字符串:

a = "Hello"
b = "Python"
c = a + " " + b  # 拼接空格
print(c)  # 输出:Hello Python

# 注意:只能拼接字符串,不能直接拼接其他类型(需先转换)
age = 20
# print("My age is " + age)  # 错误:TypeError(字符串+整数)
print("My age is " + str(age))  # 正确:转换为字符串 → 'My age is 20'

2. 重复(*

将字符串重复 n 次(n 为非负整数):

s = "ab"
print(s * 3)  # 输出:ababab
print("-" * 10)  # 输出:----------(常用作分隔线)
print(s * 0)  # 输出:''(空字符串)

3. 成员判断(in / not in

判断一个字符串是否是另一个字符串的子串(返回布尔值 True/False):

s = "Python is fun"
print("Python" in s)      # True("Python" 是 s 的子串)
print("java" in s)        # False
print("fun" not in s)     # False
print("is" in s)          # True

4. 长度计算(len()

用内置函数 len() 获取字符串的长度(每个 Unicode 字符算1个长度):

print(len("hello"))        # 5
print(len("中文 Python"))  # 8("中文"2个 + 空格1个 + "Python"6个)
print(len(""))             # 0(空字符串长度)

5. 最大值/最小值(max() / min()

返回字符串中字符 Unicode 编码最大/最小的字符(仅对非空字符串有效):

s = "abc123"
print(max(s))  # 'c'(Unicode 编码:'c'>'b'>'a'>'3'>'2'>'1')
print(min(s))  # '1'

五、字符串的内置方法(核心重点)

Python 为字符串提供了大量内置方法(str.方法名()),用于字符串的修改、查找、替换、判断等操作。所有方法均返回新字符串/结果,不改变原字符串(因字符串不可变)。

1. 大小写转换

方法功能示例输出
lower()全部转为小写"HELLO Python".lower()‘hello python’
upper()全部转为大写"hello Python".upper()‘HELLO PYTHON’
capitalize()首字母大写,其余小写"hello PYTHON".capitalize()‘Hello python’
title()每个单词首字母大写(分隔符:非字母)"hello python 2024".title()‘Hello Python 2024’
swapcase()大小写反转"Hello Python".swapcase()‘hELLO pYTHON’
s = "PyThOn 编程"
print(s.lower())      # 'python 编程'
print(s.title())      # 'Python 编程'(中文不影响)

2. 去除空白字符

空白字符包括:空格 、制表符 \t、换行符 \n、回车符 \r 等。

方法功能示例输出
strip()去除字符串两端的空白字符" \thello\n ".strip()‘hello’
lstrip()去除字符串左端的空白字符" \thello\n ".lstrip()'hello\n ’
rstrip()去除字符串右端的空白字符" \thello\n ".rstrip()’ \thello’
strip(chars)去除两端指定的字符(chars为字符串)"###hello###".strip("#")‘hello’
# 去除两端的特定字符(如逗号、空格)
s = ",  hello world! ,"
print(s.strip(", "))  # 输出:'hello world!'(去除逗号和空格)

3. 查找与替换

(1)查找子串(返回索引或 -1
方法功能示例输出
find(sub)从左查找子串sub,返回第一个匹配的起始索引;无匹配返回 -1"abcabc".find("ab")0
rfind(sub)从右查找子串sub,返回第一个匹配的起始索引;无匹配返回 -1"abcabc".rfind("ab")3
index(sub)与find()一致,但无匹配时抛出 ValueError"abc".index("d")报错
rindex(sub)与rfind()一致,但无匹配时抛出 ValueError"abc".rindex("d")报错
count(sub)统计子串sub出现的次数(无匹配返回0)"abcabcab".count("ab")3
s = "Python is a good language, Python is easy"
print(s.find("Python"))    # 0(第一个Python的起始索引)
print(s.rfind("Python"))   # 28(最后一个Python的起始索引)
print(s.count("is"))       # 2("is"出现2次)
print(s.find("Java"))      # -1(无匹配)
(2)替换子串(返回新字符串)
方法功能示例输出
replace(old, new)将所有old子串替换为new"abab".replace("a", "x")‘xbxb’
replace(old, new, count)替换前count个old子串"ababab".replace("a", "x", 2)‘xbxbab’
s = "I love Python, Python is great"
s_new1 = s.replace("Python", "Java")  # 替换所有Python
print(s_new1)  # 输出:'I love Java, Java is great'

s_new2 = s.replace("Python", "Java", 1)  # 只替换第一个Python
print(s_new2)  # 输出:'I love Java, Python is great'

4. 分割与连接

(1)分割字符串(返回列表)

将字符串按指定分隔符拆分,返回列表(列表元素为子字符串)。

方法功能示例输出
split(sep)按sep分割(默认sep为空白字符),忽略首尾空白"a b c".split()[‘a’,‘b’,‘c’]
split(sep, maxsplit)按sep分割,最多分割maxsplit次"a,b,c,d".split(",", 2)[‘a’,‘b’,‘c,d’]
rsplit(sep, maxsplit)从右向左分割,最多maxsplit次"a,b,c,d".rsplit(",", 2)[‘a,b’,‘c’,‘d’]
splitlines()按换行符(\n、\r\n等)分割,默认不保留换行"a\nb\r\nc".splitlines()[‘a’,‘b’,‘c’]
splitlines(keepends=True)保留换行符"a\nb".splitlines(True)[‘a\n’,‘b’]
# 1. 按逗号分割
s1 = "apple,banana,orange"
print(s1.split(","))  # 输出:['apple', 'banana', 'orange']

# 2. 按空格分割(默认)
s2 = "hello   world  python"  # 多个空格视为一个分隔符
print(s2.split())  # 输出:['hello', 'world', 'python']

# 3. 限制分割次数
s3 = "a-b-c-d-e"
print(s3.split("-", 3))  # 分割3次 → ['a', 'b', 'c', 'd-e']

# 4. 按换行分割
s4 = "第一行\n第二行\r\n第三行"
print(s4.splitlines())  # 输出:['第一行', '第二行', '第三行']
(2)连接列表(返回字符串)

用字符串作为分隔符,将列表中的元素连接为一个新字符串(列表元素必须是字符串类型)。

方法:分隔符.join(列表)

# 1. 用逗号连接
fruits = ["apple", "banana", "orange"]
print(", ".join(fruits))  # 输出:'apple, banana, orange'

# 2. 用空字符串连接(拼接列表元素)
chars = ["P", "y", "t", "h", "o", "n"]
print("".join(chars))  # 输出:'Python'

# 3. 用换行符连接(多行字符串)
lines = ["第一行", "第二行", "第三行"]
print("\n".join(lines))  # 输出:第一行\n第二行\n第三行(换行显示)

# 错误:列表元素包含非字符串(需先转换)
nums = [1, 2, 3]
# print("-".join(nums))  # 报错:TypeError
print("-".join(str(num) for num in nums))  # 正确 → '1-2-3'

5. 判断字符串类型(返回布尔值)

这类方法用于判断字符串是否满足特定条件(如是否全是字母、是否是数字等),常用于数据校验。

方法功能示例输出
isalpha()是否全是字母(含中文等Unicode字母)"Python编程".isalpha()True
isdigit()是否全是数字(0-9,不含小数点)"12345".isdigit()True
isnumeric()是否全是数值(含数字、汉字数字、罗马数字)"123四Ⅴ".isnumeric()True
isalnum()是否全是字母或数字(含Unicode)"Python123".isalnum()True
isspace()是否全是空白字符(空格、\t、\n等)" \t\n".isspace()True
islower()是否全是小写字母"hello".islower()True
isupper()是否全是大写字母"HELLO".isupper()True
istitle()是否是标题格式(每个单词首字母大写)"Hello World".istitle()True
startswith(prefix)是否以prefix开头(可加start/end参数)"Python".startswith("Py")True
endswith(suffix)是否以suffix结尾(可加start/end参数)"Python".endswith("on")True
# 数据校验示例:判断输入是否为纯数字
user_input = input("请输入年龄:")
if user_input.isdigit():
    age = int(user_input)
    print(f"年龄:{age}")
else:
    print("输入错误!请输入数字。")

# startswith/endswith 加范围参数
s = "abcdef"
print(s.startswith("bc", 1, 4))  # 从索引1到3(不包含4)是否以"bc"开头 → True
print(s.endswith("de", 2, 5))    # 从索引2到4是否以"de"结尾 → True

六、字符串格式化(拼接变量的优雅方式)

字符串格式化用于将变量嵌入字符串中,比 + 拼接更灵活、可读性更强。Python 支持3种主流格式化方式,推荐优先使用 f-string(Python3.6+)。

1. f-string(格式化字符串字面值,推荐)

语法:在字符串前加 fF,变量/表达式用 {} 包裹,直接嵌入字符串。

基本用法
name = "Tom"
age = 20
height = 1.75

# 1. 嵌入变量
print(f"我叫{name},今年{age}岁,身高{height}米。")
# 输出:我叫Tom,今年20岁,身高1.75米。

# 2. 嵌入表达式(直接计算)
print(f"明年我{age+1}岁,身高的2倍是{height*2}米。")
# 输出:明年我21岁,身高的2倍是3.5米。

# 3. 嵌入函数调用
print(f"名字大写:{name.upper()},名字长度:{len(name)}。")
# 输出:名字大写:TOM,名字长度:3。
格式控制(保留小数、对齐等)

{变量:格式说明} 中添加格式符,控制输出格式:

# 1. 保留小数(:.nf → 保留n位小数)
pi = 3.1415926
print(f"π ≈ {pi:.2f}")  # 保留2位 → 3.14
print(f"π ≈ {pi:.4f}")  # 保留4位 → 3.1416

# 2. 数字补零/对齐(:n>m → 右对齐,不足m位补n;:n<m → 左对齐)
num = 123
print(f"右对齐(补0,5位):{num:0>5}")  # 00123
print(f"左对齐(补-,5位):{num:-<5}")  # 123--

# 3. 千位分隔符(:,)
salary = 1234567
print(f"工资:{salary:,} 元")  # 1,234,567 元

# 4. 百分比格式(:.n% → 保留n位小数,转为百分比)
rate = 0.789
print(f"通过率:{rate:.1%}")  # 78.9%

2. str.format() 方法(兼容Python2/3)

语法:用 {} 作为占位符,通过 format() 传入变量/值,按顺序或关键字匹配。

# 1. 按顺序匹配
print("我叫{},今年{}岁。".format("Tom", 20))  # 我叫Tom,今年20岁。

# 2. 按索引匹配(可重复使用)
print("第1个:{0},第2个:{1},再第1个:{0}".format("a", "b"))  # 第1个:a,第2个:b,再第1个:a

# 3. 按关键字匹配
print("我叫{name},身高{height}米。".format(name="Tom", height=1.75))  # 我叫Tom,身高1.75米。

# 4. 格式控制(与f-string一致)
pi = 3.1415926
print("π ≈ {:.2f}".format(pi))  # 3.14
print("工资:{:,} 元".format(1234567))  # 1,234,567 元

3. % 格式化(老式方法,不推荐)

语法:类似C语言的 printf,用 % 作为占位符,后续跟变量元组。

占位符含义示例输出
%s字符串"名字:%s" % “Tom”名字:Tom
%d整数"年龄:%d" % 20年龄:20
%f浮点数"身高:%.2f" % 1.75身高:1.75
%x十六进制数"十六进制:%x" % 255十六进制:ff
name = "Tom"
age = 20
height = 1.75
print("我叫%s,今年%d岁,身高%.2f米。" % (name, age, height))
# 输出:我叫Tom,今年20岁,身高1.75米。

✅ 推荐优先级:f-string > str.format() > % 格式化(f-string 最简洁、高效)。

七、字符串编码与解码(处理文件/网络数据)

字符串在计算机中存储和传输时,需要将 Unicode 字符转换为字节序列(编码);读取时再将字节序列转回 Unicode 字符(解码)。

1. 编码(str → bytes):encode()

语法:字符串.encode(encoding="utf-8", errors="strict")

  • encoding:编码格式(默认 utf-8,常用还有 gbkgb2312
  • errors:编码错误处理方式(strict 报错、ignore 忽略、replace 替换为 ?
s = "中文 Python"

# 1. UTF-8编码(推荐,兼容所有语言)
bytes_utf8 = s.encode("utf-8")
print(bytes_utf8)  # 输出:b'\xe4\xb8\xad\xe6\x96\x87 Python'(b开头表示bytes类型)

# 2. GBK编码(仅支持中文,字节数更少)
bytes_gbk = s.encode("gbk")
print(bytes_gbk)  # 输出:b'\xd6\xd0\xce\xc4 Python'

# 3. 处理编码错误(如用gbk编码日文)
s2 = "中文 こんにちは"
# bytes_gbk_error = s2.encode("gbk")  # 报错:UnicodeEncodeError
bytes_gbk_ignore = s2.encode("gbk", errors="ignore")  # 忽略无法编码的字符
print(bytes_gbk_ignore)  # 输出:b'\xd6\xd0\xce\xc4 '

2. 解码(bytes → str):decode()

语法:字节序列.decode(encoding="utf-8", errors="strict")

  • 解码时的 encoding 必须与编码时一致,否则会出现乱码或报错。
# 1. UTF-8解码(对应上面的UTF-8编码)
bytes_utf8 = b'\xe4\xb8\xad\xe6\x96\x87 Python'
s_utf8 = bytes_utf8.decode("utf-8")
print(s_utf8)  # 输出:中文 Python

# 2. GBK解码(对应上面的GBK编码)
bytes_gbk = b'\xd6\xd0\xce\xc4 Python'
s_gbk = bytes_gbk.decode("gbk")
print(s_gbk)  # 输出:中文 Python

# 3. 错误解码(用utf-8解码gbk字节序列 → 乱码)
s_wrong = bytes_gbk.decode("utf-8")
print(s_wrong)  # 输出:�й� Python(乱码)

✅ 实际应用场景:

  • 读取文件时指定编码(open("file.txt", "r", encoding="utf-8")
  • 网络请求/响应数据的编码转换(如 requests 库的 response.encoding = "utf-8"

八、字符串高级用法

1. 正则表达式(复杂字符串处理)

当需要实现模糊匹配、复杂查找/替换(如提取手机号、邮箱、替换所有符合规则的子串)时,使用 re 模块(正则表达式)。

简单示例:提取字符串中的数字
import re

s = "我的手机号是13812345678,年龄25岁,工资12345.67元"

# 1. 提取所有数字(包括整数和小数)
numbers = re.findall(r"\d+\.?\d*", s)
print(numbers)  # 输出:['13812345678', '25', '12345.67']

# 2. 提取手机号(11位数字)
phone = re.findall(r"1[3-9]\d{9}", s)
print(phone)  # 输出:['13812345678']

# 3. 替换所有数字为"*"
s_new = re.sub(r"\d", "*", s)
print(s_new)  # 输出:我的手机号是***********,年龄**岁,工资*****.**元

2. 高效字符串操作技巧

  • 避免频繁拼接:大量字符串拼接时,用 list.append() 收集后再 join(),比 + 高效(+ 每次都会创建新字符串):

    # 低效(频繁创建新字符串)
    s = ""
    for i in range(1000):
        s += str(i)
    
    # 高效(仅创建1次最终字符串)
    lst = []
    for i in range(1000):
        lst.append(str(i))
    s = "".join(lst)
    
  • 字符串常量池:Python 会缓存短字符串(通常长度≤20),重复使用时直接引用,而非创建新对象:

    a = "hello"
    b = "hello"
    print(a is b)  # 输出:True(同一对象)
    
    c = "hello world" * 10  # 长字符串,不缓存
    d = "hello world" * 10
    print(c is d)  # 输出:False(不同对象)
    

九、常见问题与注意事项

  1. 不可变性误区:试图通过索引修改字符串会报错,需用拼接/切片创建新字符串。
  2. 转义字符混淆:路径、正则表达式中尽量用原始字符串(r""),避免 \ 转义问题。
  3. 编码乱码:文件读取/网络传输时,确保编码格式一致(优先用 utf-8)。
  4. 格式化类型匹配%d 只能接收整数,%f 接收浮点数,误用会报错(如 "%d" % 3.14 报错,需用 "%d" % int(3.14))。
  5. 中文长度计算len("中文") 输出 2(每个中文是1个Unicode字符),而非字节数("中文".encode("utf-8") 是6个字节)。

总结

字符串是 Python 中最基础且核心的数据类型,掌握以下重点即可应对90%的场景:

  1. 字符串的创建(3种引号、转义字符、原始字符串);
  2. 索引与切片(访问和截取字符串);
  3. 核心方法(大小写、去空白、查找替换、分割连接、类型判断);
  4. 格式化(优先用 f-string);
  5. 编码解码(处理文件/网络数据)。

建议多通过实际案例练习(如文本处理、数据清洗),加深对字符串方法和特性的理解!

更多推荐