文章目录
- [一 LEGB作用域](#一 LEGB作用域)
- [二 re(Regular Expression)](#二 re(Regular Expression))
-
- 预览
- [1. `re.match()` ------ 从字符串开头匹配](#1.
re.match()
—— 从字符串开头匹配) - [2. `re.search()` ------ 搜索整个字符串](#2.
re.search()
—— 搜索整个字符串) - [3. `re.findall()` ------ 返回所有匹配的字符串列表](#3.
re.findall()
—— 返回所有匹配的字符串列表) - [4. `re.finditer()` ------ 返回所有匹配的迭代器](#4.
re.finditer()
—— 返回所有匹配的迭代器) - [5. `re.sub()` ------ 替换匹配的字符串](#5.
re.sub()
—— 替换匹配的字符串) - [6. `re.split()` ------ 按正则表达式分割字符串](#6.
re.split()
—— 按正则表达式分割字符串) - [7. `re.compile()` ------ 预编译正则表达式](#7.
re.compile()
—— 预编译正则表达式) - [8. `Match` 对象的常用方法](#8.
Match
对象的常用方法)
- [三 正则表达式](#三 正则表达式)
-
- [1. 基本字符匹配](#1. 基本字符匹配)
- [2. 元字符(特殊字符)](#2. 元字符(特殊字符))
- [3. 预定义字符集(转义字符)](#3. 预定义字符集(转义字符))
- [4. 贪婪匹配 vs 非贪婪匹配](#4. 贪婪匹配 vs 非贪婪匹配)
- [5. 分组与捕获](#5. 分组与捕获)
- [6. 零宽断言](#6. 零宽断言)
- [7. 常用正则示例](#7. 常用正则示例)
一 LEGB作用域
global关键字:在函数内部修改全局变量时,必须在函数内部定义全局变量(全局声明)。
nonlocal关键字:在内层函数修改外层嵌套函数内的变量时,也要在内层声明
L(Local)
局部作用域:函数内部
python
import math
# 判断是否是素数
def is_prime(n):
if n <= 1:
return False
if n == 2:
# 唯一偶数中的素数
return True
if n % 2 == 0:
# 排除所有的偶数
return False
# 只需判断到 sqrt(n)的奇数因子
max_divisor = math.isqrt(n) + 1
for i in range(3, max_divisor, 2):
if n % i == 0:
return False
return True
"""
其中 max_divisor 是局部变量
"""
E(Enclosing)
嵌套作用域:嵌套作用域是指在函数内部可以访问外部函数定义的变量。每当创建一个新的函数,就会创建一个新的嵌套作用域
python
def outer():
n = 1
# 嵌套函数
def inner0():
print(f'初始时外层函数变量n={n}')
# 嵌套函数
def inner1():
nonlocal n # 声明外部变量
n += 1 # 修改外部变量
inner0()
print(f"内层函数执行前n={n}")
inner1()
print(f"内层函数执行后n={n}")
outer()
"""
运行结果:
初始时外层函数变量n=1
内层函数执行前n=1
内层函数执行后n=2
"""
G(Global)
全局作用域:模块(.py文件)内部
python
import math
# 判断是否是素数
def is_prime(n):
pass # 上述代码
nums = [1, 5, 6, 10] # 全局变量
for num in nums:
print(f'{num}是素数吗? {is_prime(num)}')
"""
运行结果:
1是素数吗? False
5是素数吗? True
6是素数吗? False
10是素数吗? False
"""
B(Builtin)
内置模块作用域:builtins.py文件
二 re(Regular Expression)
Python 的
re
模块提供了正则表达式(Regular Expression)操作,用于字符串的匹配、查找、替换和分割等操作。
预览
方法 | 功能 | 返回值 |
---|---|---|
re.match() |
从字符串开头匹配 | Match 或 None |
re.search() |
搜索整个字符串 | Match 或 None |
re.findall() |
返回所有匹配的列表 | list |
re.finditer() |
返回所有匹配的迭代器 | iterator |
re.sub() |
替换匹配的字符串 | str |
re.split() |
按正则表达式分割 | list |
re.compile() |
预编译正则表达式 | Pattern |
1. re.match()
------ 从字符串开头匹配
功能 :
从字符串的起始位置 开始匹配正则表达式,如果匹配成功返回 Match
对象,否则返回 None
。
语法:
python
re.match(pattern, string, flags=0)
参数:
pattern
:正则表达式模式。string
:要匹配的字符串。flags
:可选标志(如re.IGNORECASE
忽略大小写)。
示例:
python
import re
result = re.match(r'hello', 'hello world')
print(result.group()) # 输出: 'hello'
result = re.match(r'world', 'hello world')
print(result) # 输出: None(因为 'world' 不在开头)
2. re.search()
------ 搜索整个字符串
功能 :
扫描整个字符串,返回第一个 匹配的 Match
对象,如果没有匹配则返回 None
。
语法:
python
re.search(pattern, string, flags=0)
示例:
python
import re
result = re.search(r'world', 'hello world')
print(result.group()) # 输出: 'world'
result = re.search(r'python', 'hello world')
print(result) # 输出: None
3. re.findall()
------ 返回所有匹配的字符串列表
功能 :
返回字符串中所有 匹配的子串组成的列表(不返回 Match
对象)。
语法:
python
re.findall(pattern, string, flags=0)
示例:
python
import re
result = re.findall(r'\d+', 'a1b22c333')
print(result) # 输出: ['1', '22', '333']
4. re.finditer()
------ 返回所有匹配的迭代器
功能 :
返回一个迭代器,包含所有匹配的 Match
对象(比 findall
更灵活,可以获取匹配的位置)。
语法:
python
re.finditer(pattern, string, flags=0)
示例:
python
import re
matches = re.finditer(r'\d+', 'a1b22c333')
for match in matches:
print(match.group(), match.span())
# 输出:
# '1' (1, 2)
# '22' (3, 5)
# '333' (6, 9)
5. re.sub()
------ 替换匹配的字符串
功能 :
用指定的字符串替换所有匹配的子串,并返回替换后的字符串。
语法:
python
re.sub(pattern, repl, string, count=0, flags=0)
参数:
repl
:替换的字符串(或函数)。count
:最多替换次数(默认0
表示全部替换)。
示例:
python
import re
result = re.sub(r'\d+', 'X', 'a1b22c333')
print(result) # 输出: 'aXbXcX'
# 使用函数替换
def double_num(match):
return str(int(match.group()) * 2)
result = re.sub(r'\d+', double_num, 'a1b22c333')
print(result) # 输出: 'a2b44c666'
6. re.split()
------ 按正则表达式分割字符串
功能 :
用正则表达式匹配的子串作为分隔符,分割字符串并返回列表。
语法:
python
re.split(pattern, string, maxsplit=0, flags=0)
示例:
python
import re
result = re.split(r'\d+', 'a1b22c333d')
print(result) # 输出: ['a', 'b', 'c', 'd']
result = re.split(r'[\s,;]+', 'a,b; c d')
print(result) # 输出: ['a', 'b', 'c', 'd']
7. re.compile()
------ 预编译正则表达式
功能 :
将正则表达式编译成一个 Pattern
对象,提高多次匹配的效率。
语法:
python
re.compile(pattern, flags=0)
示例:
python
import re
pattern = re.compile(r'\d+') # 预编译
result = pattern.findall('a1b22c333')
print(result) # 输出: ['1', '22', '333']
8. Match
对象的常用方法
re.match()
和 re.search()
返回 Match
对象,常用方法:
group()
:返回匹配的字符串。start()
:返回匹配的起始位置。end()
:返回匹配的结束位置。span()
:返回(start, end)
元组。
示例:
python
import re
match = re.search(r'\d+', 'a1b22c333')
print(match.group()) # '1'
print(match.span()) # (1, 2)
三 正则表达式
正则表达式(Regular Expression)是一种强大的文本匹配和处理工具,它使用特定的语法规则来描述字符串的模式。
1. 基本字符匹配
字符 | 说明 | 示例 |
---|---|---|
a |
匹配字符 a |
re.match(r'a', 'apple') → 匹配 'a' |
\\ |
匹配 \ 本身 |
re.match(r'\\', '\\') → 匹配 \ |
\n |
换行符 | |
\t |
制表符 |
2. 元字符(特殊字符)
元字符 | 说明 | 示例 |
---|---|---|
. |
匹配任意单个字符 (除换行符 \n ) |
re.match(r'a.c', 'abc') → 匹配 'abc' |
^ |
匹配字符串的开头 | re.match(r'^a', 'apple') → 匹配 'a' |
$ |
匹配字符串的结尾 | re.search(r'e$', 'apple') → 匹配 'e' |
* |
匹配前一个字符 0 次或多次 | re.match(r'ab*', 'abbb') → 匹配 'abbb' |
+ |
匹配前一个字符 1 次或多次 | re.match(r'ab+', 'abbb') → 匹配 'abbb' |
? |
匹配前一个字符 0 次或 1 次 | re.match(r'ab?', 'ab') → 匹配 'ab' |
{m} |
匹配前一个字符 m 次 | re.match(r'a{2}', 'aa') → 匹配 'aa' |
{m,n} |
匹配前一个字符 m 到 n 次 | re.match(r'a{2,4}', 'aaa') → 匹配 'aaa' |
[...] |
匹配括号内任意一个字符 | re.match(r'[abc]', 'b') → 匹配 'b' |
[^...] |
匹配不在括号内的任意字符 | re.match(r'[^abc]', 'd') → 匹配 'd' |
` | ` | 或,匹配左边或右边的模式 |
() |
分组,捕获匹配的子串 | re.match(r'(ab)+', 'abab') → 匹配 'abab' |
3. 预定义字符集(转义字符)
字符 | 说明 | 示例 |
---|---|---|
\d |
匹配数字 (等价于 [0-9] ) |
re.match(r'\d', '3') → 匹配 '3' |
\D |
匹配非数字 (等价于 [^0-9] ) |
re.match(r'\D', 'a') → 匹配 'a' |
\w |
匹配单词字符(字母、数字、下划线) | re.match(r'\w', 'a') → 匹配 'a' |
\W |
匹配非单词字符 | re.match(r'\W', '@') → 匹配 '@' |
\s |
匹配空白字符 (空格、\t 、\n 等) |
re.match(r'\s', ' ') → 匹配 ' ' |
\S |
匹配非空白字符 | re.match(r'\S', 'a') → 匹配 'a' |
4. 贪婪匹配 vs 非贪婪匹配
-
贪婪匹配 (默认):尽可能匹配最长 的字符串。
pythonre.match(r'a.*b', 'axxxbxxxb') # 匹配整个 'axxxbxxxb'
-
非贪婪匹配 (加
?
):尽可能匹配最短 的字符串。pythonre.match(r'a.*?b', 'axxxbxxxb') # 只匹配 'axxxb'
5. 分组与捕获
语法 | 说明 | 示例 |
---|---|---|
(pattern) |
捕获分组 | re.match(r'(\d+)-(\d+)', '123-456') → 分组 ('123', '456') |
(?:pattern) |
非捕获分组(不保存匹配结果) | re.match(r'(?:\d+)-(\d+)', '123-456') → 只捕获 '456' |
(?P<name>pattern) |
命名分组 | re.match(r'(?P<year>\d{4})', '2023') → 分组名 year |
6. 零宽断言
语法 | 说明 | 示例 |
---|---|---|
(?=pattern) |
正向先行断言(后面必须匹配) | re.search(r'a(?=b)', 'ab') → 匹配 'a' (后面是 b ) |
(?!pattern) |
负向先行断言(后面不能匹配) | re.search(r'a(?!b)', 'ac') → 匹配 'a' (后面不是 b ) |
(?<=pattern) |
正向后行断言(前面必须匹配) | re.search(r'(?<=a)b', 'ab') → 匹配 'b' (前面是 a ) |
(?<!pattern) |
负向后行断言(前面不能匹配) | re.search(r'(?<!a)b', 'cb') → 匹配 'b' (前面不是 a ) |
7. 常用正则示例
场景 | 正则表达式 | 示例 |
---|---|---|
匹配邮箱 | r'[\w.-]+@[\w.-]+\.\w+' |
'user@example.com' |
匹配 URL | r'https?://[\w.-]+(?:/[\w.-]*)*' |
'https://example.com' |
匹配手机号 | r'1[3-9]\d{9}' |
'13800138000' |
匹配日期 | r'\d{4}-\d{2}-\d{2}' |
'2023-10-01' |
提取 HTML 标签内容 | r'<(\w+)>(.*?)</\1>' |
'<h1>Title</h1>' → 分组 ('h1', 'Title') |
推荐使用 Regex101 在线工具测试正则表达式!