文章目录
- 第七章 Python系统模块
- 7.1. 模块和包
- 7.1.1. 模块
- 7.1.2. 第三方模块下载
- 7.1.2.1. 替换国内源
- 7.1.2.2. pip常用命令
- 7.1.2.3. 模块之间的互相调用
- 7.1.3. 包
- 7.2. 可迭代类型
- 7.2.1. 可迭代对象与迭代器对象
- 7.2.2. 自定义迭代器
- 7.2.2.1. 自定义迭代器遍历其他序列
- 7.2.3. 生成器
- 简单表达式
- 函数生成器
- 生成器特点
- 7.3. 时间模块
- 7.3.1. time
- 7.3.2. datetime
- 7.3.3. calendar模块
- 7.4. 数学模块
- 7.5. 随机数模块
- 7.6. 字符串模块
- 7.7. hashlib加密模块
- 7.8. base64模块
- 7.9. collections模块
- 7.10. 正则模块
- 7.10.1. 正则的介绍
- 7.10.2. 常用元字符
- 7.10.3. Python的正则基本处理
- 7.10.4. 示例代码
第七章 Python系统模块
7.1. 模块和包
7.1.1. 模块
所谓的“模块”,其实就是指的py文件!模块之间是可以互相调用的!
在Python中,模块分为三种:
- 系统模块:Python环境安装完成之后自带的py文件或者包
- 自定义模块:就是我们自己写的py文件
- 第三方模块:其他人写好的,上传到 pypi.org 上面,可以下载下来使用的模块
7.1.2. 第三方模块下载
下载第三方模块最简单的方式,就是使用 pip 工具来下载。我们在安装Python环境的时候,pip命令已经安装完成了。
7.1.2.1. 替换国内源
pip可以去搜索和下载仓库中的第三方的模块,但是这些仓库在远端,使用到的是国外的镜像仓库,有些第三方模块在下载的时候可能会比较慢。因此在实际的使用中,我们经常会将镜像源替换成国内的源。
常见的国内的镜像有:
阿里云:http://mirrors.aliyun.com/pypi/simple/
清华大学:https://pypi.tuna.tsinghua.edu.cn/simple/
中国科学技术大学:http://pypi.mirrors.ustc.edu.cn/simple/
百度:https://mirror.baidu.com/pypi
豆瓣:http://pypi.douban.com/simple/
如果我们在下载第三方模块的时候,临时指定使用指定的源进行下载,可以这样做:
# 指定阿里云的源,下载PyMySQL
pip install -i http://mirrors.aliyun.com/pypi/simple PyMySQL
但是每一次都这样去指定源下载,会非常的麻烦。那么能不能一劳永逸的解决问题?此时我们可以修改配置文件来达到这个效果。
- Windows:
- 需要修改的文件是:C:\Users\{当前用户}\AppData\Roaming\pip\pip.ini,如果没有这个文件,就手动创建一下。
- macOS、Linux:
- 需要修改的文件是:~/.pip/pip.info
写入如下内容,并保存
[global]
index-url=http://mirrors.aliyun.com/pypi/simple
trusted-host=mirrors.aliyun.com
7.1.2.2. pip常用命令
# 查看版本
pip --version
# 安装指定的包
pip install PyMySQL # 安装PyMySQL的最新版本
pip install PyMySQL==1.0.4 # 安装PyMySQL的指定版本
# 升级包
pip install --upgrade PyMySQL # 升级PyMySQL,也可以使用==指定版本号
# 卸载包
pip uninstall PyMySQL # 卸载PyMySQL
# 列出已经安装的包
pip list
# 显示安装包的信息
pip show PyMySQL
# 查看指定安装包的详细信息
pip show -f PyMySQL
7.1.2.3. 模块之间的互相调用
模块之间是可以互相调用的,在使用之前要先引入指定的模块。引入的语法有三种:
python"># 1. 使用模块中的内容的时候,需要使用 模块名.内容
import 模块名
# 2. 使用内容的时候,直接操作即可
from 模块名 import 内容1, 内容2
# 3. 引入模块中的所有内容,需要注意的是如果模块下使用了 __all__规定了对外够哦那个开的内容,那么只能够引入这些内容
from 模块名 import *
python"># my.py
__all__ = ['test_method']
class NumberTool:
@staticmethod
def add(*args):
s = 0
for n in args:
s += n
return s
def test_method():
print("test_method")
# use1.py
import my
print(my.NumberTool.add(10, 20, 30)) # 需要使用 模块.内容 的方式来访问
print(my.test_method())
# use2.py
from my import NumberTool
print(NumberTool.add(10, 20, 30)) # 可以直接使用内容来访问
# test_method() # 这个函数是访问不到的
# use3.py
from my import *
test_method() # 直接访问,但是只能访问到 __all__ 中定义的部分
7.1.3. 包
一个py文件就是一个模块,那么将多个具有相关联的功能的模块组织到一起,就是一个包。其实包和目录的功能类似,都可以将若干个功能相似的模块组织到一起,我们在使用到这些模块的时候,就可以直接通过这样的目录结构,找到对应的模块来使用。
包和文件夹的区别,目前也就是包下会有一个 _init_.py 的文件了。
可以理解为,包含 _init_.py 的文件夹就是包,不包含的就是普通的文件夹。
在Python2的版本中,没有_init_.py的时候,是无法导入这个包下的模块中的内容的。
但是Python3中已经不限制了,有没有_init_.py都可以正常导入包下的模块中的内容。
那么,这个_init_.py文件是干嘛的?
其实现在就只有一个预加载的作用了。我们在导入一个包的时候,会先执行这个包下的_init_.py文件中的代码。因此我们就可以在这个文件中进行一些预处理操作。
7.2. 可迭代类型
7.2.1. 可迭代对象与迭代器对象
collections包下的abc模块中,有一个Iterable,表示可迭代类型。可迭代类型即可以依次获取到每一个元素,可以使用for-in遍历。
python">from collections.abc import Iterable
print(isinstance(10, Iterable)) # False
print(isinstance('abc', Iterable)) # True
print(isinstance([], Iterable)) # True
print(isinstance(map(str, [10, 20, 30]), Iterable)) # True
在遍历可迭代类型的时候,有些是使用别的序列在记录遍历位置,有些则是自己在记录遍历位置。那么,记录着迭代位置的对象,就是一个“迭代器”。
python">from collections.abc import Iterator
print(isinstance(10, Iterator)) # False
print(isinstance('abc', Iterator)) # False
print(isinstance([], Iterator)) # False
print(isinstance(map(str, [10, 20, 30]), Iterator)) # True
python">'''
迭代器序列的数据的特点:
取值只能向前 不能向后 取出之后 迭代器中就没有这个数据了
除了可以使用for-in进行遍历之外 还可以使用next(序列)获取序列中的元素
'''
s = 'hello'
for ch in s:
print(ch)
print('===')
for ch in s:
print(ch)
print('===')
'''
可迭代类型 非迭代器序列类型的数据 在遍历的时候 先创建一个迭代器对象 用它来记录位置 逐个获取元素
'''
# 迭代器序列类型的数据 先把自身设置迭代器【记录自身位置】 然后逐个取值
seq = map(str, [10, 20, 30])
for ele in seq:
print(ele)
print('====')
for ele in seq:
print(ele)
7.2.2. 自定义迭代器
在一个类中定义了 _iter_ 魔术方法的,就可以称为是可迭代对象了。这个方法需要返回一个迭代器对象,可以是自己,也可以是其他对象。
在一个类中同时定义了 _iter_ 和 __next__ 魔术方法的,就可以称为是迭代器对象了。
在使用for-in遍历可迭代对象的时候,其实是先获取到迭代器对象,然后每一次循环都调用__next__方法,获取到下一个元素。
python">class Fibonacci:
def __init__(self, bound):
self.bound = bound # 记录边界
# 记录从几开始遍历
self.current = 1
# 记录前两位的数字
self.number_1 = 1
self.number_2 = 1
# 记录当前的数字
self.current_number = 1
def __iter__(self):
return self
def __next__(self):
if self.current <= self.bound:
if self.current > 2:
self.current_number = self.number_1 + self.number_2
# 为下一位做准备
self.number_1 = self.number_2
self.number_2 = self.current_number
# 位数+1
self.current += 1
return self.current_number
else:
# raise ValueError("后面没有了")
raise StopIteration
fib = Fibonacci(10)
for ele in fib:
print(ele)
for ele in fib:
print(ele)
print(isinstance(fib, Iterable))
print(isinstance(fib, Iterator))
7.2.2.1. 自定义迭代器遍历其他序列
python">class MySequenceIterator:
def __init__(self, seq):
self.seq = seq # 记录需要遍历的序列
self.current = 0 # 记录当前遍历到的位置
def __iter__(self):
return self # 以自己作为迭代器
def __next__(self):
if self.current < len(self.seq):
# 获取到指定位的元素
value = self.seq[self.current]
# 迭代位置自增
self.current += 1
# 返回处理之后的数据
return str(value).title()
else:
raise StopIteration
# 创建一个序列
l = ["hello world", "python language", "hadoop distributed file system", "mysql database"]
for e in MySequenceIterator(l):
print(e)
7.2.3. 生成器
生成器是一种特殊的迭代器,支持迭代器的所有的操作。使用生成器主要用来生成一个序列的。
生成器分为两种:
- 简单表达式:类似于列表推导式
- 函数生成器:定义一个函数,用来生成一系列的数据,将return换成yield即可
简单表达式
python"># 列表推导式,直接生成一个列表
l1 = [f"{x:03d}" for x in range(1, 200) if x % 7 == 0 and x % 3 == 0]
print(l1)
# 简单表达式生成器,获取到一个生成器对象
l2 = (f"{x:03d}" for x in range(1, 200) if x % 7 == 0 and x % 3 == 0)
print(l2) # <generator object <genexpr> at 0x10474b780>
print(next(l2)) # 021
print(next(l2)) # 042
函数生成器
python">def get_generator():
for i in range(5, 10000, 5):
if i % 3 == 0:
yield i
"""
return: 结束函数,并把结果返回到调用的位置
yield: 根据逻辑,将数据产出并暂停生产。当下一次获取数据的时候,继续生产数据
"""
gen = get_generator()
print(next(gen))
print(next(gen))
生成器特点
生成器并不直接生成全部的数据,而是根据数据生成的逻辑,每次调用next的时候,才会生成一个元素
因此,生成器常用于在程序中使用大量的数据的时候,此时会有明显的内存占用的效果
7.3. 时间模块
7.3.1. time
python">import time
# 1. 获取当前时间对应的时间元组
time_tuple = time.localtime()
print(time_tuple)
# time.struct_time(tm_year=2022, tm_mon=8, tm_mday=30, tm_hour=14, tm_min=43, tm_sec=15, tm_wday=1, tm_yday=242, tm_isdst=0)
# 年
year = time_tuple[0]
print(year)
# 还可以根据类属性名获取相关的信息
month = time_tuple.tm_mon
print(month) # 8
# 2. 获取当前时间对应的时间戳 [应该是个整型 Python设计成了浮点型]
timestamp = time.time() # 从当前时间到1970年1月1日经历的秒数
print(timestamp) # 1661842192.4782896
print(int(timestamp)) # 1661842192
# 3. 时间格式化 【按照指定的格式把时间显式出来】 --- 结果是字符串
# time.strftime('展示的时间格式', 时间元组)
'''
时间格式的展示不是随便写的 是需要用指定的时间代表占位符来设置格式的
'''
print(time.strftime('%Y/%m/%d %H:%M:%S', time_tuple)) # 2022/08/30 14:57:47
print(time.strftime('%Y/%m/%d %p %I:%M:%S', time_tuple)) # 2022/08/30 PM 02:58:12
print(time.strftime('%Y/%m/%d %p %I:%M:%S %w %j', time_tuple)) # 2022/08/30 PM 02:58:49 2 242
# w 星期 j是一年中的第几天
# 4. 时间反格式化 ----> 时间元组
# time.strptime(特定格式的字符串显式的时间, '解析字符串格式时间的占位模板')
'''
字符串格式的时间 要和 解析模板要对应好
'''
new_time = time.strptime('2022-08-20 19:22:37', '%Y-%m-%d %H:%M:%S')
print(new_time)
# time.struct_time(tm_year=2022, tm_mon=8, tm_mday=20, tm_hour=19, tm_min=22, tm_sec=37, tm_wday=5, tm_yday=232, tm_isdst=-1)
# 5.获取时间元组对应的时间戳
print(time.mktime(new_time)) # 1660994557.0
# 6. 将时间戳 转化为时间元组
print(time.localtime(1660994000))
# time.struct_time(tm_year=2022, tm_mon=8, tm_mday=20, tm_hour=19, tm_min=13, tm_sec=20, tm_wday=5, tm_yday=232, tm_isdst=0)
# 7. 时间休眠
time.sleep(10)
print('睡醒了')
7.3.2. datetime
python">import datetime
# datetime.date
# datetime.datetime
# datetime.time
# datetime.timedelta
# 1.构造时间
date = datetime.date(2022, 8, 20)
print(date, type(date)) # 2022-08-20 <class 'datetime.date'>
datetime0 = datetime.datetime(2022, 8, 13)
print(datetime0, type(datetime0)) # 2022-08-13 00:00:00 <class 'datetime.datetime'>
time = datetime.time(17, 22, 34)
print(time, type(time)) # 17:22:34 <class 'datetime.time'>
# 2. 获取当前时间
cur_datetime = datetime.datetime.now()
print(cur_datetime, type(cur_datetime)) # 2022-08-30 15:41:00.270011 <class 'datetime.datetime'>
# 3. 获取datetime date日期
print(cur_datetime.date()) # 2022-08-30
print(cur_datetime.year) # 2022
print(cur_datetime.month, cur_datetime.day, cur_datetime.hour, cur_datetime.minute, cur_datetime.second)
print(cur_datetime.weekday()) # 星期
# 4. 对时间进行格式化
'时间对象.strftime(格式化模板)'
print(cur_datetime.strftime('%Y/%m/%d %p %I:%M:%S')) # 2022/08/30 PM 03:44:24
# 5. 时间反格式化
'''
类方法
datetime.datetime.strptime(字符串格式的时间, 反格式化模板)
'''
dt = datetime.datetime.strptime('2020-11-30 22:37:45', '%Y-%m-%d %H:%M:%S')
print(dt, type(dt)) # 2020-11-30 22:37:45 <class 'datetime.datetime'>
# 6. 获取时间戳
# 时间对象.timestamp()
print(cur_datetime.timestamp()) # 1661845623.276597
# 7. 时间戳转时间
# 类方法
print(datetime.datetime.fromtimestamp(1661844000)) # 2022-08-30 15:20:00
# 8. 时间差
d1 = datetime.datetime(2022, 7, 31)
d2 = datetime.datetime(2022, 5, 16, 17, 56, 24)
time_diff = d1 - d2
print(time_diff, type(time_diff)) # 75 days, 6:03:36 <class 'datetime.timedelta'>
# 只获取差的天数
print(time_diff.days) # 75
print(f'减去天数之外 剩余时间对应的秒数 {time_diff.seconds}') # 减去天数之外 剩余时间对应的秒数 21816
print(f'包含天数在内的时间全部转化为秒数 {time_diff.total_seconds()}') # 包含天数在内的时间全部转化为秒数 6501816.0
now = datetime.datetime.now()
print(now)
# 三天后的时间
print(now + datetime.timedelta(days=3))
# 一星期前的时间
print(now - datetime.timedelta(weeks=1))
7.3.3. calendar模块
python">import calendar
print(calendar.calendar(2022)) # 这一年的日历
print(calendar.month(2022, 8)) # 某一年 某个月的日历
print(calendar.isleap(2020)) # True 判断年是否为闰年
print(calendar.leapdays(1990, 2020)) # 7 闰年的个数
7.4. 数学模块
python">import math
print(f'取绝对值 {math.fabs(-234)}') # 取绝对值 234.0
print(f'求指定数的幂数 {math.pow(2, 4)}') # 求指定数的幂数 16.0
print(f'无精度损失的求和 {math.fsum([0.1] * 10)}') # 无精度损失的求和 1.0
print(f'可能会存在精度损失的求和 {sum([0.1] * 10)}') # 可能会存在精度损失的求和 0.9999999999999999
print(f'向上取整【大于或者等于数据 且最接近于数据的整数】 {math.ceil(19.5)}') # 向上取整【大于或者等于数据 且最接近于数据的整数】 20
print(f'向上取整【大于或者等于数据 且最接近于数据的整数】 {math.ceil(-19.5)}') # 向上取整【大于或者等于数据 且最接近于数据的整数】 -19
print(f'向上取整【大于或者等于数据 且最接近于数据的整数】 {math.ceil(19.1)}') # 向上取整【大于或者等于数据 且最接近于数据的整数】 20
print(f'向下取整【小于或者等于数据 且最接近于数据的整数】 {math.floor(19.0)}') # 向下取整【小于或者等于数据 且最接近于数据的整数】 19
print(f'向下取整【小于或者等于数据 且最接近于数据的整数】 {math.floor(19.9)}') # 向下取整【小于或者等于数据 且最接近于数据的整数】 19
print(f'阶乘 {math.factorial(5)}') # 阶乘 120
print(f'对数函数 {math.log2(32)}') # 对数函数 5.0
print(f'圆周率 {math.pi}') # 圆周率 3.141592653589793
print(f'三角函数 {math.sin(math.pi/6)}') # 三角函数 0.49999999999999994
print(f'三角函数 {math.tan(math.pi/4)}') # 三角函数 0.9999999999999999
print(f'角度转化为弧度 {math.radians(90)}') # 角度转化为弧度 1.5707963267948966
print(f'弧度转换为角度 {math.degrees(math.pi/3)}') # 弧度转换为角度 59.99999999999999
7.5. 随机数模块
python">import random
# 在指定的序列中随机选择一个元素
ele = random.choice('qwertyuiopasdfghjklzxcvbnm')
print(ele)
ele = random.choice(range(3, 100, 10))
print(ele)
# 在指定的序列中随机选择指定个数的元素 [选择出来的可能会重复]
eles = random.choices('qwertyuiopasdfghjklzxcvbnm', k=5)
print(eles)
# vlaues = []
# for i in range(5):
# ele = random.choice('qwertyuiopasdfghjklzxcvbnm')
# vlaues.append(ele)
# 在指定的序列中随机选择指定个数的元素 [选择出来的不会重复]
eles = random.sample('qwertyuiopasdfghjklzxcvbnm', k=5)
print(eles)
# 作业 【自己写逻辑 定义一个函数 在指定序列中选择不重复的指定个数的数据】
# 在指定的范围中随机选择一个整数 [唯一一个前闭后闭]
print(random.randint(10, 30))
# 在[0, 1)中随机选择一个小数
print(random.random())
# random.randrange() ===> random.choice(range())
nums = [12, 34, 56, 82, 19, 30]
# 随机的打乱列表中的元素
random.shuffle(nums)
print(nums)
# 设置随机种子
'''
随机算法 --- 起始数据源 一般是当前时间
当没有范围 产生的随机数肯定是不一样
数据存在范围 产生的结果可能会重复
当数据起源值是一样的 产生的结果就是一样的
'''
print(random.randint(1, 100000))
random.seed(10)
print(random.randint(1, 100000))
# random.seed(10)
print(random.randint(1, 100000))
print(random.random())
7.6. 字符串模块
python">import string
'''
whitespace = ' \t\n\r\v\f'
ascii_lowercase = 'abcdefghijklmnopqrstuvwxyz'
ascii_uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
ascii_letters = ascii_lowercase + ascii_uppercase
digits = '0123456789'
hexdigits = digits + 'abcdef' + 'ABCDEF'
octdigits = '01234567'
punctuation = r"""!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
printable = digits + ascii_letters + punctuation + whitespace
'''
print(string.ascii_letters)
print(string.whitespace)
7.7. hashlib加密模块
python">import hashlib
# md5 16字节 128位 【16个单字节的符号】
# 1. 获取md5加密操作
md5 = hashlib.md5()
md5.update('1abcde56721A@1234'.encode('utf-8'))
# 获取加密摘要
print(md5.hexdigest()) # fcea920f7412b5da7be0cf42b8c93759
md5 = hashlib.md5()
md5.update('1234'.encode('utf-8'))
md5.update('567'.encode('utf-8'))
# 获取加密摘要
print(md5.hexdigest()) # fcea920f7412b5da7be0cf42b8c93759
# sha家族
sha1 = hashlib.sha1()
sha1.update('1234567890'.encode('utf-8'))
print(sha1.hexdigest())
sha256 = hashlib.sha256()
sha256.update('1234567890'.encode('utf-8'))
print(sha256.hexdigest()) # c775e7b757ede630cd0aa1113bd102661ab38829ca52a6422ab782862f268646
7.8. base64模块
python"># base64: 是目前网络上最常见的用于传输字节序列的编码方式
import base64
# 编码
b64_data = base64.b64encode('hell world'.encode('utf8'))
print(b64_data)
# 解码
print(base64.b64decode('aGVsbCB3b3JsZA==').decode('utf8'))
7.9. collections模块
python">from collections import defaultdict, Counter, deque, namedtuple
d0 = {'a': 97, 'b': 98}
# print(d0['c'])
# print(d0.get('c'))
# def get_value():
# return 0
# 给不存在的键设置默认值 可以使用defaultdict
d1 = defaultdict(lambda : 0)
d1.update(d0)
print(d1)
print(d1['c']) # 0
# Counter 也是字典的一个子类
# 专门来做词频统计的 统计序列中每个元素出现的次数
s = 'aaabbbc333cccbdddaaaa333'
count_dict = Counter(s)
print(count_dict)
# Counter({'a': 7, '3': 6, 'b': 4, 'c': 4, 'd': 3})
print(count_dict.most_common(3)) # 提起排名前几的内容信息
# deque 队列
'''
队列分为单向和双向队列
单向队列 规则是先进先出
deque 是双向队列
'''
queue = deque()
queue.append(10)
queue.append(12)
print(queue)
queue.appendleft(19)
queue.appendleft(21)
print(queue)
queue.pop()
print(queue)
queue.popleft()
print(queue)
# namedtuple 根据类型和属性名构造一个类 既有面向对象的特性 又有元组的特性 [元组的子类]
Point = namedtuple('Point', ('x', 'y'))
p = Point(18, 22)
print(p) # Point(x=18, y=22)
# 取属性可以通过下标 也可以通过属性名
x = p[0]
print(x)
y = p.y
print(y)
7.10. 正则模块
7.10.1. 正则的介绍
正则表达式,并不是Python独有的,而是一套独立的、自成体系的知识点。在很多语言中,都有对正则的使用。
正则表达式是用来做字符串的校验、匹配的工作的,其实正则表达式只有一个作用:验证一个字符串是否与指定的规则匹配。
但是,在很多的语言中,都在匹配的基础上,添加了其他的功能。
python">"""
需求:验证一个字符串,是否是一个合法的QQ号码
1、一个QQ号码由6到12位的数字组成,不能包含其他部分
2、一个QQ号码不能以数字0作为开头
"""
def check_qq_number(number):
s = str(number)
# 验证长度
if not 6 <= len(s) <= 12:
return False
# 验证纯数字
if not s.isdigit():
return False
# 验证不以0开头
if s.startswith('0'):
return False
return True
def check_qq_number_with_re(number):
return re.compile('[1-9]\\d{5,11}').fullmatch(number) is not None
print(check_qq_number_with_re('012345678'))
7.10.2. 常用元字符
元字符 | 意义 |
---|---|
^ | 匹配一个字符串的开头。 在fullmatch的正则匹配中,可以省略不写。 |
$ | 匹配一个字符串的结尾。 在fullmatch的正则匹配中,可以省略不写。 |
[] | 匹配一位字符。 [abc]: 表示这一位的字符, 可以是a、也可以是b、也可以是c 。 [a-z]: 表示这一位的字符, 可以是 [a, z] 范围内的任意的字符。 [a-zABC]: 表示这一位的字符, 可以是 [a,z ] 范围内的任意字符, 或者A、或者B、或者C 。 [a-zA-Z]: 表示这一位的字符, 可以是任意的字母, 包括大写字母和小写字母。 [^abc]: 表示这一位的字符, 可以是除了 a、b、c 之外的任意字符。 |
\ | 转义字符。 |
\d | 匹配所有的数字, 等同于 [0-9] 。 |
\D | 匹配所有的非数字, 等同于 [^0-9] 。 |
\w | 匹配所有的单词字符, 等同于 [a-zA-Z0-9_] 。 |
\W | 匹配所有的非单词字符, 等同于 [^a-zA-Z0-9_] 。 |
. | 通配符, 可以匹配一个任意的字符。 |
+ | 前面的一位或者一组字符, 连续出现了一次或多次。 |
? | 前面的一位或者一组字符, 连续出现了一次或零次。 |
* | 前面的一位或者一组字符, 连续出现了零次、一次或多次。 |
{} | 对前面的一位或者一组字符出现次数的精准匹配。 {m} : 表示前面的一位或者一组字符连续出现了m次。 {m,} : 表示前面的一位或者一组字符连续出现了至少m次。 {m,n} : 表示前面的一位或者一组字符连续出现了至少m次,最多n次。 |
| | 作用于整体或者是一个分组, 表示匹配的内容, 可以是任意的一个部分。 abc|123|opq : 表示整体的部分, 可以是 abc, 也可以是 123, 也可以是 opq |
() | 分组。 把某些连续的字符视为一个整体对待。 |
7.10.3. Python的正则基本处理
Python中的正则表达式基本使用
pattern_obj = re.compile(正则语法规则, 匹配的标记格式)
涉及到的几个类
re.Pattern: 正则表达式对象,用来描述正则表达式
re.Match: 匹配结果对象,用来描述正则匹配的结果,包含匹配的位置和匹配的内容
.group(): 获取到匹配的内容
.group(N): 获取匹配到的第N组的内容
.group(group_name): 获取匹配到的指定组名的内容
.span(): 获取到匹配的位置
常用方法
python">pattern_obj.match('字符串') 从前往后查找匹配项,找到了就返回匹配的部分(Match对象),找不到返回None
pattern_obj.fullmatch('字符串') 用指定的正则语法规则,匹配整个的字符串,能够匹配就返回匹配部分(Match对象),匹配不到就返回None
pattern_obj.search('字符串') 在指定的字符串中查找满足规则的子串,返回第一个匹配部分(Match对象),找不到就返回None
pattern_obj.findall('字符串') 在指定的字符串中查找所有满足规则的子串,返回一个列表
pattern_obj.finditer('字符串') 在指定的字符串中查找所有的匹配项,返回迭代器(迭代Match对象)
pattern_obj.split('字符串') 将一个字符串使用指定的正则切割
pattern_obj.sub(替换函数,字符串,替换数量) 将匹配到的每一个部分,使用指定函数处理,并替换掉原有的内容
re包简化
在re包的_init_.py文件中定义了若干个函数,用来简化上述方法的使用。
python">re.match('正则表达式', '字符串')
re.match('正则表达式', '字符串')
re.fullmatch('正则表达式', '字符串')
re.search('正则表达式', '字符串')
re.findall('正则表达式', '字符串')
re.finditer('正则表达式', '字符串')
re.split('正则表达式', '字符串')
re.sub('正则表达式', '替换函数','字符串','替换数量')
匹配标记格式
re.I 忽略大小写的匹配
re.M 多行匹配,会影响到^和$
re.S 使.可以匹配包括换行符在内的所有字符
7.10.4. 示例代码
python">import re
"""
1、基础元字符匹配
"""
res1 = re.fullmatch('<div>.+</div>', '<div><p>hello</p></div>')
if res1 is not None:
print(res1.group(), res1.span())
"""
2、分组的匹配
"""
res2 = re.fullmatch('(\\w{6,16})@(?P<company_name>126|163|qq|gmail|yahoo)\\.com', 'test_youxiang@163.com')
if res2 is not None:
print(res2.groups()) # 获取到所有分组
print(res2.group(1)) # 按照序号获取分组
print(res2.group('company_name')) # 按照名字获取分组
"""
3、按照正则切割
"""
res3 = re.split('\\d+', 'hello123world4python456mysql')
print(res3) # ['hello', 'world', 'python', 'mysql']
"""
4、按照正则替换
"""
res4 = re.sub('\\d+', ', ', 'tom123jerry33lilei45lucy')
print(res4) # tom, jerry, lilei, lucy