第三章 字符串来咯
字符串是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 |
浙公网安备 33010602011771号