Python: 字符串基础

编程中打交道最多的数据类型不是数字,而是文本。用户名、邮箱、文章内容、JSON 数据、网页 HTML……全是字符串。这一课系统学习 Python 中字符串的各种操作。


1. 字符串的三种引号

Python 允许用三种方式定义字符串:

PYTHON
# 单引号
s1 = 'Hello'

# 双引号
s2 = "Hello"

# 三引号(多行字符串)
s3 = """这是第一行
这是第二行
这是第三行"""

单引号和双引号没有区别,选一种保持一致就好:

PYTHON
# 以下两种写法等价
name = 'Charlie'
name = "Charlie"

但如果你需要在字符串中包含引号本身,就需要混合使用:

PYTHON
# 字符串里有单引号,外面用双引号
text = "It's a beautiful day"
print(text)              # It's a beautiful day

# 字符串里有双引号,外面用单引号
text = '他说:"你好!"'
print(text)              # 他说:"你好!"

# 或者用转义符(不推荐,可读性差)
text = 'It\'s a beautiful day'
💡 提示:推荐统一使用双引号。原因:英文文本中常见缩略符(don't、it's)用单引号,如果你外部也用单引号就需要转义。双引号能省去这个麻烦。

(1) 三引号:多行文本的好帮手

三引号("""''')可以保留文本的换行和格式:

PYTHON
# 用三引号写多行文本
message = """尊敬的顾客,您好!

感谢您选择我们的服务。您的订单已确认。
预计送达时间:3 个工作日内。

如有疑问,请联系客服。
祝您生活愉快!"""

print(message)

运行结果:

TEXT 📖 仅展示
尊敬的顾客,您好!

感谢您选择我们的服务。您的订单已确认。
预计送达时间:3 个工作日内。

如有疑问,请联系客服。
祝您生活愉快!

三引号常用于:长文本、文档注释、函数说明。



2. 转义字符

有些字符不能直接在字符串里写(比如换行、制表符、引号本身),需要用转义字符来表示——在字符前面加一个反斜杠 \

转义符 含义
\n 换行
\t 制表符(Tab)
\\ 反斜杠本身
\' 单引号
\" 双引号
PYTHON
print("第一行\n第二行")           # \n 换行
print("姓名:Alice\t年龄:25岁")   # \t 制表符对齐
print("C:\\Users\\Charlie\\桌面")    # \\ 输出反斜杠
print("他说:\"你好!\"")         # \" 双引号

运行结果:

TEXT 📖 仅展示
第一行
第二行
姓名:Alice	年龄:25岁
C:\Users\Charlie\桌面
他说:"你好!"

▶ 示例:格式化输出表格(难度⭐)

PYTHON
# 用 \t 对齐输出表格
print("商品\t单价\t数量\t总价")
print("------------------------")
print("苹果\t5.0\t3\t15.0")
print("香蕉\t3.5\t5\t17.5")
print("牛奶\t12.0\t2\t24.0")
▶ 试一试

运行结果:

TEXT 📖 仅展示
商品	单价	数量	总价
------------------------
苹果	5.0	3	15.0
香蕉	3.5	5	17.5
牛奶	12.0	2	24.0
💡 提示:制表符 \t 常用于对齐文本,但如果内容长度不一,对齐效果可能不完美。正式场景建议用 f-string 的格式控制({value:10} 表示占用 10 个字符宽度)。



3. 原始字符串

如果你写过 Windows 文件路径,一定遇到过这样的痛苦:

TEXT 📖 仅展示
# 糟糕!\n 被解释成了换行
path = "C:\Users\new_folder\documents"
print(path)
# 输出:C:\Users
#        ew_folder\documents

解决办法:在字符串前面加 r,告诉 Python"不要处理转义符,原样输出":

PYTHON
# ✅ 原始字符串——r 前缀
path = r"C:\Users\new_folder\documents"
print(path)
# 输出:C:\Users\new_folder\documents

原始字符串(raw string)中的每个字符都是它自己,\n 不再表示换行,\t 不再表示制表符。

PYTHON
# 正则表达式中的原始字符串(后面会用到)
pattern = r"\d{3}-\d{8}"   # 匹配电话号码:010-12345678

# 文件路径
log_path = r"D:\logs\app\2026\06\error.log"

print(f"日志路径:{log_path}")
⚠️ 注意:原始字符串的最后一个字符不能是反斜杠——r"abc\" 会报错。因为 \" 虽然不被当成转义符处理,但 Python 解析器会认为引号被转义了,导致字符串没有正常结束。



4. 字符串索引

字符串是由字符组成的序列,每个字符都有一个位置(索引)。Python 的索引从 0 开始:

PYTHON
text = "Python"
# 索引:0→P  1→y  2→t  3→h  4→o  5→n

print(text[0])    # P
print(text[1])    # y
print(text[5])    # n

Python 还支持负数索引,从右往左数,-1 是最后一个字符:

PYTHON
text = "Python"
print(text[-1])   # n(倒数第1个)
print(text[-2])   # o(倒数第2个)
print(text[-3])   # h
print(text[-6])   # P(倒数第6个,就是第一个)

(1) 索引示意图

TEXT 📖 仅展示
正索引:  0    1    2    3    4    5
       ┌────┬────┬────┬────┬────┬────┐
       │ P  │ y  │ t  │ h  │ o  │ n  │
       └────┴────┴────┴────┴────┴────┘
负索引: -6   -5   -4   -3   -2   -1

▶ 示例:提取字符信息(难度⭐)

PYTHON
# 从身份证号中提取基本信息
id_number = "110101199001011234"

# 前6位:地址码
address_code = id_number[:6]      # 切片的写法后面会讲
print(f"地址码:{address_code}")

# 第7-14位:出生日期
birth = id_number[6:14]
year = birth[:4]
month = birth[4:6]
day = birth[6:8]
print(f"出生日期:{year}年{month}月{day}日")

# 最后一位(-1):校验码
last_digit = id_number[-1]
print(f"校验码:{last_digit}")
▶ 试一试

运行结果:

TEXT 📖 仅展示
地址码:110101
出生日期:1990年01月01日
校验码:4
💡 提示string[6:14] 这种写法叫做切片(slicing),下面马上讲到。



5. 字符串切片

切片就是从字符串中取出一段子串。语法:字符串[起点:终点:步长]

PYTHON
text = "Hello, Python!"

# 基本切片:起点:终点(不包括终点)
print(text[0:5])      # Hello(第0到第4个字符)
print(text[7:13])     # Python(第7到第12个字符)

(1) 省略写法

PYTHON
text = "Hello, Python!"

print(text[:5])       # Hello——省略起点,从开头到索引5
print(text[7:])       # Python!——省略终点,从索引7到结尾
print(text[:])        # Hello, Python!——全部

(2) 步长

PYTHON
text = "Hello, Python!"

print(text[::2])      # Hlo yhn!——每2个取1个
print(text[1::2])     # el,Pto——从索引1开始每2个取1个

(3) 负数步长(反转)

PYTHON
text = "Hello, Python!"

print(text[::-1])     # !nohtyP ,olleH——反转整个字符串!
print(text[5:0:-1])   # ,olle——从索引5到0,反向取

(4) 切片示例

PYTHON
# 实用的切片技巧
url = "https://www.example.com"

# 去掉协议头
without_https = url[8:]    # www.example.com
print(without_https)

# 获取域名
domain = url[8:-4]         # www.example
print(domain)

# 反转字符串
name = "上海自来水来自海上"
reversed_name = name[::-1]   # 上海自来水来自海上(回文)
print(name == reversed_name)  # True——是回文!

# 每隔一个字符取一个
code = "H1e2l3l4o5"
clean = code[::2]           # Hello
print(clean)

运行结果:

TEXT 📖 仅展示
www.example.com
www.example
True
Hello
💡 提示[::-1] 是 Python 中反转字符串的经典写法,简单又优雅。但注意:切片永远不会报 IndexError——即使起点或终点超出了字符串长度,Python 也会安全地返回它能取到的内容。



6. 常用字符串方法

字符串有很多内置方法,这里先学最常用的几个。不需要全记——知道有这些功能就行,用多了自然记得住。

(1) 大小写转换

PYTHON
text = "Hello, Python!"

print(text.upper())         # HELLO, PYTHON!
print(text.lower())         # hello, python!
print(text.title())         # Hello, Python!
print(text.capitalize())    # Hello, python!

(2) 去除空白

PYTHON
text = "   Hello, World!   "

print(f"|{text}|")                # |   Hello, World!   |
print(f"|{text.strip()}|")        # |Hello, World!|——去掉两端
print(f"|{text.lstrip()}|")       # |Hello, World!   |——去掉左边
print(f"|{text.rstrip()}|")       # |   Hello, World!|——去掉右边

(3) 查找和替换

PYTHON
text = "Hello, Python! Python is fun!"

print(text.find("Python"))      # 7——第一次出现的位置
print(text.find("Java"))        # -1——没找到返回 -1
print(text.count("Python"))     # 2——出现次数

new_text = text.replace("Python", "Java")
print(new_text)                  # Hello, Java! Java is fun!

# replace 可以指定替换次数
partial = text.replace("Python", "Java", 1)
print(partial)                   # Hello, Java! Python is fun!

(4) 判断类方法

PYTHON
print("hello".isalpha())        # True——全是字母
print("hello123".isalpha())     # False——有数字
print("12345".isdigit())        # True——全是数字
print("hello123".isalnum())     # True——字母+数字
print("hello!".isalnum())       # False——有感叹号
print("   ".isspace())          # True——全是空白
💡 提示:这些判断方法在输入验证时非常有用。比如检查用户输入是否全是数字:if user_input.isdigit(): 可以确保 int() 转换不会出错。

(5) 拆分与合并

PYTHON
# split():字符串 → 列表
sentence = "I love Python"
words = sentence.split()
print(words)                     # ['I', 'love', 'Python']

# 指定分隔符
csv_line = "Alice,25,北京"
fields = csv_line.split(",")
print(fields)                    # ['Alice', '25', '北京']

# join():列表 → 字符串
parts = ["2026", "06", "23"]
date = "-".join(parts)
print(date)                      # 2026-06-23

▶ 示例:数据清洗(难度⭐⭐)

PYTHON
# 模拟用户输入的脏数据
raw_data = "   Alice  ,  25  ,  北京  \n"

# 清洗流程
# 1. strip() 去掉首尾空白
cleaned = raw_data.strip()
print(f"步骤1:|{cleaned}|")

# 2. split() 按逗号拆分
fields = cleaned.split(",")
print(f"步骤2:{fields}")

# 3. 每个字段再去掉多余空格
name = fields[0].strip()
age = fields[1].strip()
city = fields[2].strip()

print(f"姓名:{name}")
print(f"年龄:{age}")
print(f"城市:{city}")
▶ 试一试

运行结果:

TEXT 📖 仅展示
步骤1:|Alice  ,  25  ,  北京|
步骤2:['Alice  ', '  25  ', '  北京']
姓名:Alice
年龄:25
城市:北京


7. len():获取字符串长度

len() 是 Python 内置函数,用来获取字符串(以及其他序列)的长度:

PYTHON
text = "Hello, Python!"
print(len(text))              # 15

# 中文字符每个算 1 个长度
chinese = "你好,世界!"
print(len(chinese))           # 6

# 空字符串长度为 0
print(len(""))                # 0

# 常用场景:限制输入长度
username = "Charlie同学"
if len(username) < 2:
    print("用户名太短")
elif len(username) > 10:
    print("用户名太长")
else:
    print(f"用户名 {username} 长度合格")
💡 提示:Python 3 中的字符串长度按字符数计算,不是字节数。一个中文字符 len("中") 的结果是 1,不是 3(在 Python 2 中会是 3)。这让字符串操作更直观。



8. 常见应用场景


❓ 常见问题

Q:单引号和双引号到底选哪个?为什么 Python 允许两种? A: 历史上 Python 的设计者认为给程序员选择权是好事。不同人有不同习惯:C/Java 程序员习惯双引号,JavaScript 程序员两种都用。建议统一用双引号,因为英文中常见单引号(it's、don't、can't),外部用双引号就不用转义了。但更重要的是一个项目里保持一致,不要混用。

Q:切片时的终点为什么取不到?比如 text[0:5] 不包含索引 5? A: 这是 Python 的设计哲学——左闭右开([起点, 终点))。好处有两个:一是 text[:5] 好记(前 5 个字符),二是 text[0:5]text[5:10] 正好无缝衔接,不会漏掉也不会重叠。你习惯了会发现这个设计很舒服。

Q:find()index() 有什么区别? A: 它们功能一样,都是查找子串位置。区别是:find() 找不到时返回 -1index() 找不到时报错(ValueError)。日常用 find() 更安全。index() 适合你确定"一定存在这个子串"的场景(比如从固定格式的数据中提取信息)。

Q:为什么字符串方法不直接修改原字符串?(比如 text.upper()text 并没有变)A: 因为字符串在 Python 中是不可变的(immutable)。一旦创建就不能修改。text.upper() 实际上返回了一个新的字符串,原来的 text 保持不变。这和保护数据安全有关——如果你把一个字符串传递给某个函数,你可以确信它不会被偷偷改掉。如果你需要"修改"字符串,就用切片+拼接创建新字符串。


📖 小节


📝 作业

  1. 基础题(难度⭐):给定一个字符串 s = "Python programming is fun!",分别实现:

    • 提取前 6 个字符
    • 提取最后 4 个字符
    • 反转整个字符串
    • 将所有字母转为大写
  2. 进阶题(难度⭐⭐):写一个"邮箱格式验证器"。给定一个邮箱地址 email = "user@example.com",检查它:

    • 是否包含 @ 符号
    • @ 符号前后是否都有内容(不为空)
    • 是否以 .com.cn.org 结尾
    • 输出每条检查的结果(True/False)提示:用 find() 查找 @ 位置,用切片提取前后部分。
  3. 挑战题(难度⭐⭐⭐):写一个"脏数据清洗函数"。给定一个字符串:

    TEXT 📖 仅展示
    data = "  Alice, 25 ,  北京  ;  Bob  ,  30,  上海  ;  Charlie  ,  22,  广州  "
    

    ; 拆分出每个人的数据,再按 , 拆分出每个字段,用 strip() 去掉每个字段的空白字符,最后以整齐的表格形式输出:

    TEXT 📖 仅展示
    姓名  年龄  城市
    ─────────────────
    Alice  25   北京
    Bob  30   上海
    Charlie  22   广州
    
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏