【Python】LEGB作用域 + re模块 + 正则表达式

文章目录

  • [一 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() 从字符串开头匹配 MatchNone
re.search() 搜索整个字符串 MatchNone
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 非贪婪匹配

  • 贪婪匹配 (默认):尽可能匹配最长 的字符串。

    python 复制代码
    re.match(r'a.*b', 'axxxbxxxb')  # 匹配整个 'axxxbxxxb'
  • 非贪婪匹配 (加 ?):尽可能匹配最短 的字符串。

    python 复制代码
    re.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 在线工具测试正则表达式!

相关推荐
这个DBA有点耶2 小时前
NULL不是空——数据库里最反直觉的设计,90%新人踩过的坑
数据库·mysql·代码规范
用户8356290780512 小时前
Python 实现 PDF 文件加密与解密方法
后端·python
用户8356290780512 小时前
使用 Python 冻结与拆分 Excel 窗格教程
后端·python
这个DBA有点耶4 小时前
AI写的SQL跑崩了生产库,这锅谁背?
数据库·人工智能·程序员
镜舟科技5 小时前
Databricks 再提 LTAP,AI 时代的数据底座为何重回大一统叙事?
数据库·架构·agent
Databend6 小时前
从湖仓升级为 Agent 时代的数据控制面,Snowflake 和 Databricks 有哪些布局
大数据·数据库·agent
ClouGence9 小时前
SQL Server CDC 能放到 Always On 备库读吗?一文讲透原理与实践
数据库·sql server
你好潘先生11 小时前
别再记命令了,用 yeero do 说句人话就能跑脚本,而且不烧 token
服务器·python·命令行
Agent_大师11 小时前
WebSocket 行情重连成功,K线缺口不会自动消失
python
荣码11 小时前
LLM结构化输出:让AI返回JSON而不是废话,我踩了4个坑
java·python