一、什么是 str?
在 Python 中,str 是一个内置的不可变序列类型 ,用于表示文本数据(text) 。它由 Unicode 码位(code points) 组成,而非字节(bytes)。这是 Python 3 相较于 Python 2 的重大改进之一:明确区分文本(str)与二进制数据(bytes)。
-
类型标识 :
type("hello") is str→True -
不可变性:一旦创建,其内容无法被修改(但可以重新绑定变量)
-
序列性:支持索引、切片、迭代、成员测试等序列操作
s = "Python"
print(len(s)) # 6
print(s[0]) # 'P'
print('y' in s) # True
for char in s: print(char)
二、字符串的创建方式
1. 字面量(Literals)
| 引号类型 | 说明 |
|---|---|
'...' 或 "..." |
单行字符串,可互换使用 |
'''...''' 或 """...""" |
多行字符串(保留换行和缩进) |
r"..." |
原始字符串(raw string),不处理转义序列 |
f"..." |
格式化字符串字面量(f-string),嵌入表达式 |
b"..." |
❌ 这是 bytes,不是 str |
示例:
# 普通字符串
s1 = "Hello\nWorld" # 包含换行符
s2 = 'It\'s OK' # 转义单引号
# 多行字符串
s3 = """Line 1
Line 2
Line 3"""
# 原始字符串(常用于正则、路径)
path = r"C:\Users\name\file.txt" # 不会将 \n 解释为换行
# f-string(Python 3.6+)
name = "Alice"
age = 30
msg = f"Name: {name.upper()}, Age: {age * 2}"
⚠️ 注意:原始字符串不能以奇数个反斜杠结尾(如
r"abc\"会报错),因为最后一个\会尝试转义结束引号。
三、字符串的内部表示与 Unicode
1. Unicode 基础
Python 的 str 基于 Unicode 标准 ,每个字符对应一个 码位(code point) ,用 U+XXXX 表示。
print(ord('A')) # 65
print(chr(65)) # 'A'
print('\u03B1') # α (希腊字母 alpha)
print('\U0001F40D') # 🐍 (蛇 emoji)
2. 编码与解码(Encoding/Decoding)
虽然 str 是 Unicode 文本,但在存储或传输时需转换为字节(bytes),这就涉及编码 (encode)和解码(decode):
text = "你好"
encoded = text.encode('utf-8') # b'\xe4\xbd\xa0\xe5\xa5\xbd'
decoded = encoded.decode('utf-8') # "你好"
# 常见编码:'utf-8', 'ascii', 'latin-1', 'gbk' 等
🔒 安全提示:永远不要对未知来源的字节流使用
.decode()而不指定错误处理策略(如errors='ignore'或errors='replace'),否则可能因无效字节抛出异常。
四、字符串的不可变性(Immutability)
str 对象一旦创建,其内容不可更改。所有"修改"操作都返回新字符串。
s = "hello"
# s[0] = 'H' # ❌ TypeError: 'str' object does not support item assignment
new_s = s.replace('h', 'H') # ✅ 返回新字符串 "Hello"
优点:
- 线程安全
- 可哈希(可用作字典键、集合元素)
- 内存优化(字符串驻留机制)
缺点:
- 频繁拼接效率低(应使用
str.join()或io.StringIO)
五、字符串操作详解
1. 索引与切片(Indexing & Slicing)
支持正向(0 起始)和反向(-1 起始)索引:
s = "Python"
s[0] # 'P'
s[-1] # 'n'
s[1:4] # 'yth'
s[::2] # 'Pto' (步长为 2)
s[::-1] # 'nohtyP' (反转)
2. 成员测试
'Py' in "Python" # True
'Java' not in "Python" # True
3. 拼接(Concatenation)
-
使用
+:"a" + "b"→"ab" -
使用
+=:s += "x"(注意:每次创建新对象) -
推荐:
"".join(iterable)(高效)parts = ["Hello", "World"]
result = " ".join(parts) # "Hello World"
4. 重复
"-" * 10 # "----------"
六、字符串方法大全(分类整理)
A. 大小写转换
| 方法 | 说明 |
|---|---|
.upper() |
全大写 |
.lower() |
全小写 |
.capitalize() |
首字母大写,其余小写 |
.title() |
每个单词首字母大写 |
.swapcase() |
大小写互换 |
.casefold() |
更激进的小写(用于无大小写比较,如德语 ß → ss) |
"ß".lower() # 'ß'
"ß".casefold() # 'ss'
B. 查找与替换
| 方法 | 说明 |
|---|---|
.find(sub[, start[, end]]) |
返回首次出现位置,未找到返回 -1 |
.rfind(sub) |
从右查找 |
.index(sub) |
同 find,但未找到抛出 ValueError |
.count(sub) |
子串出现次数 |
.replace(old, new[, count]) |
替换(可限制次数) |
.partition(sep) |
分割为 (前, 分隔符, 后) 三元组 |
.rpartition(sep) |
从右分割 |
"hello world".partition(" ") # ('hello', ' ', 'world')
C. 判断类方法
| 方法 | 说明 |
|---|---|
.startswith(prefix) |
是否以某字符串开头(支持元组) |
.endswith(suffix) |
是否以某字符串结尾 |
.isalpha() |
是否全为字母 |
.isdigit() / .isnumeric() / .isdecimal() |
数字判断(有细微差别) |
.isspace() |
是否全为空白字符(空格、\t、\n 等) |
.isalnum() |
是否为字母或数字 |
.isidentifier() |
是否为合法 Python 标识符 |
.islower() / .isupper() / .istitle() |
大小写判断 |
💡
isdigit()vsisnumeric()vsisdecimal():
isdecimal():仅十进制数字(0-9)isdigit():包括上标数字(如²)isnumeric():还包括汉字数字(如"一二三")
D. 去除空白
| 方法 | 说明 |
|---|---|
.strip([chars]) |
去除首尾字符(默认空白) |
.lstrip() / .rstrip() |
仅左/右去除 |
" abc ".strip() # "abc"
"www.example.com".strip("wcom.") # "example"
E. 分割与连接
| 方法 | 说明 |
|---|---|
.split(sep=None, maxsplit=-1) |
按分隔符分割(默认按空白) |
.rsplit() |
从右分割 |
.splitlines(keepends=False) |
按行分割(处理 \n, \r\n 等) |
.join(iterable) |
连接字符串序列 |
"a,b,c".split(",") # ['a', 'b', 'c']
"line1\nline2".splitlines() # ['line1', 'line2']
F. 对齐与填充
| 方法 | 说明 |
|---|---|
.center(width[, fillchar]) |
居中 |
.ljust(width[, fillchar]) |
左对齐 |
.rjust(width[, fillchar]) |
右对齐 |
.zfill(width) |
用 0 填充到指定宽度(用于数字字符串) |
"42".zfill(5) # "00042"
"hi".center(10, '-') # "---hi----"
G. 编码相关
| 方法 | 说明 |
|---|---|
.encode(encoding='utf-8', errors='strict') |
转为 bytes |
| (无直接 decode 方法,需对 bytes 调用) |
七、格式化字符串(Formatting)
1. f-string(推荐,Python 3.6+)
功能强大、高效、可读性强:
name = "Alice"
price = 19.9
print(f"Hello {name}, price: ${price:.2f}")
# 支持表达式、函数调用、格式说明符
print(f"{2 + 3 = }") # "2 + 3 = 5"(调试用)
2. .format() 方法
"{} {}".format("Hello", "World")
"{name} is {age} years old".format(name="Bob", age=25)
"{:0>4}".format(42) # "0042"
3. % 格式化(旧式,不推荐新代码使用)
"%s is %d years old" % ("Alice", 30)
4. string.Template(安全模板,防注入)
from string import Template
t = Template("$name likes $fruit")
t.substitute(name="Alice", fruit="apple")
八、性能与最佳实践
1. 避免频繁字符串拼接
# ❌ 低效
s = ""
for i in range(1000):
s += str(i)
# ✅ 高效
parts = []
for i in range(1000):
parts.append(str(i))
s = "".join(parts)
# 或使用 f-string / format
2. 字符串驻留(String Interning)
Python 自动对某些字符串进行"驻留"(interning),使相同内容的字符串共享同一内存地址:
a = "hello"
b = "hello"
a is b # True(小字符串、标识符等会被驻留)
# 手动驻留
import sys
s1 = sys.intern("very long string that repeats")
s2 = sys.intern("very long string that repeats")
s1 is s2 # True,节省内存
注意:不要依赖
is比较字符串内容,应始终用==。
九、国际化与本地化(i18n/l10n)
-
使用
gettext模块实现多语言支持 -
字符串本身支持任意 Unicode 字符,包括中文、阿拉伯文、emoji 等
import gettext
_ = gettext.gettext
print(_("Hello")) # 可根据 locale 输出不同语言
十、常见陷阱与注意事项
-
混淆
str与bytes在读取文件、网络通信时,务必注意是否需要
.decode()或.encode()。 -
路径中的反斜杠
Windows 路径建议使用原始字符串或
pathlib:from pathlib import Path p = Path("C:/Users/name/file.txt") # 跨平台安全 -
f-string 中的引号冲突
可混合使用单双引号:
name = 'Alice' msg = f"He said, '{name}'" -
格式化精度问题
浮点数格式化注意舍入:
f"{0.1 + 0.2:.1f}" # "0.3"(尽管 0.1+0.2 != 0.3 精确值)
十一、扩展:自定义字符串行为
虽然 str 不可变,但可通过继承创建自定义字符串类(较少用):
class TitleStr(str):
def __new__(cls, content):
return super().__new__(cls, content.title())
s = TitleStr("hello world")
print(s) # "Hello World"
总结
Python 的 str 类型是一个功能丰富、设计精良的文本处理工具。掌握其核心特性(不可变、Unicode、方法体系、格式化)是编写健壮、高效 Python 代码的基础。在实际开发中,应优先使用 f-string、避免低效拼接、正确处理编码,并始终区分文本与二进制数据。