第三章 字符串来咯

字符串是python应用的大头,很多python应用(如爬取网站信息)都会用到字符串操作,前面已经讲了字符串的创建与访问,本章将继续深入字符串的操作

一、字符串常用操作

1. 查询操作(查找子串位置 / 出现次数)

(1)常见方法

方法

语法格式

核心功能

示例(以str = 'Rose, rose, I love you. Rose, rose, I fallin love with you.'为例)

find()

字符串.find(sub[, start[, end]])

查找子串sub在字符串中首次出现的位置,不存在返回-1;start/end指定查找范围(默认全串)

str.find('rose') → 6;str.find('rose', 10, 20) → -1

rfind()

字符串.rfind(sub[, start[, end]])

与find()功能一致,从字符串右侧开始查找(从后往前)

str.rfind('rose') → 30

index()

字符串.index(sub[, start[, end]])

查找子串sub首次出现位置,不存在则报ValueError异常

str.index('rose') → 6;str.index('rose', 10, 20) → 报错

rindex()

字符串.rindex(sub[, start[, end]])

与index()功能一致,从右侧开始查找

str.rindex('rose') → 30

count()

字符串.count(sub[, start[, end]])

统计子串sub在字符串中出现的次数,start/end限制范围

str.count('rose') → 2;str.count('rose', 10, 20) → 0

tip:find()和index()如何选择:优先用 find()/rfind(),慎用 index()/rindex() (index()子串未找到时抛出 ValueError 异常(中断程序),适用于确定子串一定存在,需快速报错)

(2)切片操作

通过索引范围提取子串,语法包括:

  • 字符串名[索引值]:提取单个字符,如s[2]='t'
  • 字符串名[开始索引:结束索引]:提取从开始到结束(不包含结束)的子串,省略开始默认从 0,省略结束默认到末尾,如s[1:3]='yt's[:3]='Pyt'
  • 字符串名[开始索引:结束索引:步长]:指定步长提取,步长为 2 取奇数位,步长为 - 1 逆序,如s[1::2]='to's[::-1]='nohtyP'

2. 修改操作(生成新字符串,原字符串不可变)

(1)替换与切割

方法

语法格式

核心功能

示例(以str = 'Rose, rose, I love you.'为例)

replace()

字符串.replace(old, new[, max])

将old子串替换为new,max指定最大替换次数(默认替换所有)

str.replace('rose', 'Python') → 'Rose, Python, I love you.'

split()

字符串.split(sep=None, maxsplit=-1)

按sep分隔符切割字符串,返回列表;sep=None按空白符切割,maxsplit限制切割次数

str.split(',') → ['Rose', ' rose', ' I love you.'];str.split(',', 1) → ['Rose', ' rose, I love you.']

join()

连接符.join(seq)

将序列seq(如列表、元组)的元素用连接符拼接成新字符串

'-'.join(['I', 'love', 'Python']) → 'I-love-Python'

(2)大小写转换

方法

功能描述

示例(以str = 'Rose, rose, I LOVE Python.'为例)

capitalize()

首字母大写,其余字母小写

str.capitalize() → 'Rose, rose, i love python.'

title()

每个单词首字母大写(以空白符分隔的视为单词)

str.title() → 'Rose, Rose, I Love Python.'

lower()

所有字母转为小写

str.lower() → 'rose, rose, i love python.'

upper()

所有字母转为大写

str.upper() → 'ROSE, ROSE, I LOVE PYTHON.'

swapcase()

大小写互换

str.swapcase() → 'rOSE, ROSE, i love pYTHON.'

(3)对齐与空格删除

方法

语法格式

核心功能

示例(以my_str = 'Python'为例)

ljust()

字符串.ljust(width[, fillchar])

左对齐,用fillchar(默认空格)填充至width长度,长度不足返回原字符串

my_str.ljust(10, '.') → 'Python....'

rjust()

字符串.rjust(width[, fillchar])

右对齐,填充规则同ljust()

my_str.rjust(10, '.') → '....Python'

center()

字符串.center(width[, fillchar])

居中对齐,填充规则同ljust()

my_str.center(10, '.') → '..Python..'

strip()

字符串.strip()

删除字符串头部和尾部的空白符(空格、换行\n、制表\t等)

' Python '.strip() → 'Python'

lstrip()

字符串.lstrip()

仅删除头部空白符

' Python '.lstrip() → 'Python '

rstrip()

字符串.rstrip()

仅删除尾部空白符

' Python '.rstrip() → ' Python'

(4) 判断操作(返回布尔值True/False

方法

核心功能

示例(正确返回True,错误返回False)

startswith(sub[, beg[, end]])

判断字符串在[beg, end]范围内是否以sub开头

'Python Java'.startswith('Python') → True;'Python Java'.startswith('Java', 7) → True

endswith(sub[, beg[, end]])

判断字符串在[beg, end]范围内是否以sub结尾

'Python Java'.endswith('Java') → True;'Python Java'.endswith('Python', 0, 6) → True

isalpha()

字符串至少 1 个字符,且所有字符为字母或中文

'Python' → True;'Python123' → False;'你好' → True

isdigit()

字符串仅含数字(Unicode 数字、单字节 byte 数字、全角数字,不含汉字 / 罗马数字)

'123' → True;'123'(全角) → True;'四' → False

isnumeric()

字符串仅含数字(含 Unicode、全角、汉字、罗马数字,不含 byte 数字)

'123' → True;'四' → True;'Ⅴ'(罗马) → True

isalnum()

字符串至少 1 个字符,且所有字符为字母或数字

'Python123' → True;'Python_123' → False

isspace()

字符串仅含空白符(空格、\n、\t等)

' ' → True;' Python ' → False

istitle()

字符串为标题格式(每个单词首字母大写,其余小写)

'I Love Python' → True;'I love Python' → False

islower()

字符串含至少 1 个可区分大小写的字符,且所有字符为小写

'python' → True;'Python' → False

isupper()

字符串含至少 1 个可区分大小写的字符,且所有字符为大写

'PYTHON' → True;'Python' → False

二、字符串格式化:format()方法

1. 核心语法

format()方法通过{}:代替传统%占位符,返回格式化后的新字符串(原字符串不变),语法为:

模板字符串.format(*args, **kwargs)

  • args:位置参数,按顺序传递值;
  • *kwargs:关键字参数,按名称传递值。

2. 常见使用方式

(1)位置参数
  • 不指定序号:{}按出现顺序匹配位置参数;
  • 指定序号:{n}
  • (n 为 0 开始的整数)按序号匹配位置参数,支持重复使用。
  • 示例:
# 不指定序号
str1 = '{}的学号是{},{}的年龄是{}'print(str1.format('李四', 1002, '李四', 22))  # 李四的学号是1002,李四的年龄是22# 指定序号
str2 = '{0}的学号
# 指定序号
str2 = '{0}的学号是{1},{0}的年龄是{2}'print(str2.format('李四', 1002, 22))  # 李四的学号是1002,李四的年龄是22是{1},{0}的年龄是{2}'print(str2.format('李四', 1002, 22))  # 李四的学号是1002,李四的年龄是22
(2)关键字参数

{key}通过关键字匹配参数,参数顺序可任意调整。

示例:

str3 = '{name}的学号是{sno},{name}的年龄是{age}'

print(str3.format(name='张三', sno=1001, age=20)) # 张三的学号是1001,张三的年龄是20

(3)对象属性

{对象.属性}可直接引用对象的属性值,适用于自定义类或内置对象。

示例:

class Student:
     def __init__(self, name, sno, age):
         self.name = name
         self.sno = sno
         self.age = age
 s = Student('小明', 2001, 20)
 str4 = '{stu.name}的学号是{stu.sno},{stu.name}的年龄是{stu.age}'
 print(str4.format(stu=s))  # 小明的学号是2001,小明的年龄是20

三、正则表达式基础

tip:与re模块一起看

1. 概念与作用

正则表达式是特殊字符序列,用于匹配、检索、替换字符串中符合特定模式的内容,广泛应用于文本处理(如敏感词过滤、信息提取)和爬虫数据解析。

2. 核心语法(普通字符 + 特殊字符)

(1)普通字符与字符集
  • 普通字符:精确匹配单个字符(如a匹配'a'123匹配'123');
  • 字符集[]:匹配括号内任意一个字符,支持范围表示和取反:
    • [0-9]:匹配任意数字(等价于\\d);
    • [a-z]:匹配任意小写字母;
    • [A-Za-z0-9_]:匹配任意字母、数字、下划线(等价于\\w);
    • [^0-9]:匹配非数字字符(等价于\\D^[]内表示取反)。
(2)特殊字符(匹配规则控制)

特殊字符

描述

示例

.

匹配除换行符\n外的任意单个字符

'a.b'匹配'a1b'、'aab',不匹配'a\nb'

^

匹配字符串开头(多行模式下匹配每行开头)

'^Python'匹配'Python Java',不匹配'Java Python'

$

匹配字符串结尾(多行模式下匹配每行结尾)

'Python$'匹配'Java Python',不匹配'Python Java'

?

匹配前面的字符 0 次或 1 次(非贪婪匹配)

'ab?'匹配'a'、'ab',不匹配'abb'

*

匹配前面的字符 0 次或多次(贪婪匹配)

'ab*'匹配'a'、'ab'、'abb'

+

匹配前面的字符 1 次或多次(贪婪匹配)

'ab+'匹配'ab'、'abb',不匹配'a'

{n}

匹配前面的字符恰好 n 次

'a{2}'匹配'aa',不匹配'a'、'aaa'

{m,n}

匹配前面的字符 m~n 次(m≤次数≤n)

'a{2,3}'匹配'aa'、'aaa'

()

分组,将括号内的内容视为一个整体,可通过group()提取分组结果

'(ab)+'匹配'ab'、'abab'

|

逻辑 “或”,匹配两侧任意一个模式(左匹配成功后不再向右匹配)

'a|b'匹配'a'或'b';'Python|Java'匹配'Python'或'Java'

\

转义符,将特殊字符转为普通字符(如'\.'匹配.,'\*'匹配'*')

'a\.b'仅匹配'a.b',不匹配'a1b'

(3)特殊序列(简化常用模式)

特殊序列

描述

等价形式

\d

匹配任意数字

[0-9]

\D

匹配任意非数字字符

[^0-9]

\w

匹配字母、数字、下划线

[A-Za-z0-9_]

\W

匹配非字母、非数字、非下划线

[^A-Za-z0-9_]

\s

匹配任意空白符(空格、\n、\r、\t、\f)

[ \f\n\r\t]

\S

匹配任意非空白符

[^ \f\n\r\t]

\b

匹配单词边界(单词与非单词字符的分隔处,如空格、标点)

-

\B

匹配非单词边界

-

\A

仅匹配字符串开头(同^,不受多行模式影响)

-

\Z

仅匹配字符串结尾(同$,不受多行模式影响)

-

(4)贪婪与非贪婪匹配
  • 贪婪匹配:尽可能多匹配字符(默认),如.*(点星),量词*, +, ?, {n,m}
  • 非贪婪匹配:尽可能少匹配字符,如.*?(点星问),量词*?, +?, ??, {n,m}?
  • 示例:
#数字匹配
content = 'Hello 1234567 World'
# 贪婪匹配:.*匹配到'Hello 123456',仅保留最后1个数字给(\d+)
re_pat1 = re.compile(r'^He.*(\d+).*World$', re.I)
print(re_pat1.findall(content))# ['7']
# 非贪婪匹配:.*?仅匹配'Hello ',保留完整数字给(\d+)
re_pat2 = re.compile(r'^He.*?(\d+).*World$', re.I)
print(re_pat2.findall(content))  # ['1234567']
text = "123456789"
# 贪婪 - 匹配前几个字符
greedy2 = re.findall(r'^\d{3,5}', text)
print("贪婪 ^\\d{3,5}:", greedy2)  # ['12345'] - 取最大值5
# 非贪婪 - 匹配最少字符
lazy2 = re.findall(r'^\d{3,5}?', text)
print("非贪婪 ^\\d{3,5}?:", lazy2)  # ['123'] - 取最小值3

tip:正则表达式前加上 r 表示这是一个原生字符串(raw string),可让字符串中的反斜杠 \ 等保持其原始含义,而不进行转义处理(否则应写为\\d+)

同时对于需保留的字符还是要用\转义:

text = "a+b*c.d?e^f$g(h)i{j}k[l]m\\n"
# 这些字符在正则中都有特殊含义,需要转义
special_chars = r'\.*+?^$[]{}()|\\'
pattern = r'\.|\*|\+|\?|\^|\$|\[|\]|\{|\}|\(|\)|\\|\|'
matches = re.findall(pattern, text)
print("特殊字符:", matches)  # ['+', '*', '.', '?', '^', '$', '(', ')', '{', '}', '[', ']', '\\']
  • 使用贪婪匹配:
    • 知道要匹配的内容特征
    • 性能要求高的场景
    • 使用否定字符类 [^...] 代替 .*?
  • 使用非贪婪匹配:
    • 提取多个相似模式时
    • HTML/XML标签处理
    • 引号内容提取
    • 当贪婪匹配产生意外结果时

四、re模块(正则表达式工具)

1. 核心函数与用法

re模块提供正则表达式的编译、匹配、查找、替换等功能,需先导入import re(内置的)。

函数

语法格式

核心功能

示例

compile()

re.compile(pattern, flags=0)

将正则表达式字符串pattern编译为Pattern对象,便于重复使用(提升效率);flags指定匹配模式

pat = re.compile(r'Python', re.I)(re.I表示忽略大小写)

match()

re.match(pattern, string, flags=0)

从字符串开头匹配模式,成功返回Match对象,失败返回None

re.match(r'Python', 'Python Java', re.I) → 匹配成功;re.match(r'Java', 'Python Java') → None

search()

re.search(pattern, string, flags=0)

在字符串任意位置匹配模式,找到第一个匹配返回Match对象,失败返回None

re.search(r'Java', 'Python Java', re.I) → 匹配成功

findall()

re.findall(pattern, string, flags=0)

查找字符串中所有匹配的子串,返回列表(分组匹配时返回元组列表)

re.findall(r'Python', 'Python Java Python', re.I) → ['Python', 'Python']

finditer()

re.finditer(pattern, string, flags=0)

功能同findall(),但返回迭代器(节省内存,需遍历获取结果)

iter = re.finditer(r'Python', 'Python Java Python', re.I);for m in iter: print(m.group()) → 输出两个Python

split()

re.split(pattern, string, maxsplit=0, flags=0)

按匹配的子串分割字符串,返回列表;maxsplit指定最大分割次数(0 为不限制)

re.split(r'\d+', 'one1two2three') → ['one', 'two', 'three']

sub()

re.sub(pattern, repl, string, count=0, flags=0)

替换匹配的子串为repl,count指定最大替换次数(0 为不限制),返回新字符串

re.sub(r'\d+', '-', 'one1two2three') → 'one-two-three'

subn()

re.subn(pattern, repl, string, count=0, flags=0)

功能同sub(),但返回元组(新字符串, 替换次数)

re.subn(r'\d+', '-', 'one1two2three') → ('one-two-three', 2)

2. 关键参数:flags匹配模式

模式标志

描述

re.I

忽略大小写(Ignore case)

re.M

多行模式(Multi-line):^匹配每行开头,$匹配每行结尾

re.S

单行模式(Dot matches all):.可匹配包括换行符\n在内的任意字符

re.X

忽略正则表达式中的空白符和注释(便于编写复杂正则)

re.U

按 Unicode 字符集解析(默认)

re.A

按 ASCII 码解析字符

3. Match对象方法(获取匹配结果)

match()/search()匹配成功时,返回Match对象,可通过以下方法获取细节:

方法

功能描述

示例(以m = re.search(r'h(\w+)(\s\w+)', 'hello python')为例)

group([num])

获取匹配的字符串:num=0(默认)返回整体匹配,num>0返回第num个分组结果

m.group(0) → 'hello python';m.group(1) → 'ello';m.group(2) → ' python'

groups()

返回所有分组匹配结果的元组

m.groups() → ('ello', ' python')

span([group])

返回匹配结果的起止位置(元组(start, end)):group指定分组(默认 0)

m.span() → (0, 12);m.span(1) → (1, 5)

start([group])

返回匹配结果的开始位置:group指定分组(默认 0)

m.start() → 0;m.start(2) → 5

end([group])

返回匹配结果的结束位置:group指定分组(默认 0)

m.end() → 12;m.end(2) → 12