python进阶篇-day07-高级语法与正则

day07-python其他高级语法

一. with(上下文管理)

介绍

概述

一个类只要实现了__ enter __ ()__ exit __ ()方法, 这个类就是一个上下文管理器类, 该类的对象 = 上下文管理器对象

目的

节约资源, 提高效率, 避免手动释放资源, 且出bug的时候, 也会自动尝试释放资源

特点

  1. 上下文管理器对象, 可以结合with语句使用

  2. 在with语句执行前, 会自动调用__ enter __ () 方法(要有返回对象), 用于初始化某些变量

  3. 在with语句执行后, 会自动调用 __ exit __ ()方法, 用于清理某些资源, 即使前面有bug也会调用该方法

演示

案例: 自定义文件操作

# 1. 定义1个上下文管理器类, 表示: 我们自己的处理文件的操作.
class MyFile:# 2. 在 init魔法方法中, 初始化: 属性信息.def __init__(self, file_name, mode):# 文件名(文件路径)self.file_name = file_name# 模式, r, w...self.mode = mode# 文件对象self.file_obj = None
​# 3. 在enter魔法方法中, 获取1个: 文件对象, 用于读写文件操作.def __enter__(self):print('我是 enter 魔法方法')# 获取文件对象self.file_obj = open(self.file_name, self.mode, encoding='utf-8')# 返回文件对象.# return self           # self = MyFile的对象return self.file_obj  # file_obj = open()对象
​# 4. 在exit魔法方法中, 关闭文件对象.def __exit__(self, exc_type, exc_val, exc_tb):self.file_obj.close()print('文件对象已被关闭...')
​
​
# 5. 在main方法中, 测试自定义的 文件对象.
if __name__ == '__main__':# 如果 enter魔法方法返回的是: open()对象, 代码如下with MyFile('./1.txt', 'r') as file_obj:# print( 10 / 0)    # 即使有Bug, 也会尝试关闭资源.data = file_obj.read()print(f'读取到: {data}')
​# 如果 enter魔法方法返回的是: MyFile对象, 代码如下.# with MyFile('./1.txt', 'r') as mf:#     # print( 10 / 0)    # 即使有Bug, 也会尝试关闭资源.#     data = mf.file_obj.read()#     print(f'读取到: {data}')

图解

二. 生成器

注意事项:

  1. 获取生成器生成的数据: next()函数, 遍历

  2. 如果使用超出生成式范围的数据,会报错

  3. next()移动指针, 未使用生成器数据时, 指针停留在第一个数据前, 用完所有数据后指针停留在最后一个后面, 再次遍历输出为空, 直接取值报错(超出范围)

名词解释:

名词解释: 迭代 迭代指的是: 逐个的从容器类型中获取每一个元素的过程, 称之为: 迭代(遍历) 例如: 列表, 集合, 字典, 生成器等, 都是可以遍历(迭代)的, 所以它们也称之为: 可迭代对象.

介绍

概述

生成器指的是generator对象, 他不是像以往一样, 一次生成所有的数据, 而是用一个, 产生一个, 基于用户写的规则(条件)来生成数据, 如果条件不成立, 则结束生成

目的 | 好处

节约资源 , 减少内存的占用

生成器推导式

方式1: 推导式

尝试写一个'元组推导式'(没有元组推导式这种说法 => 它是生成器)

# 案例: 演示推导式写法, 获取生成器对象.
if __name__ == '__main__':# 1. 回顾: 列表推导式.list1 = [i for i in range(1, 6)]print(f'list1: {list1}')             # [1, 2, 3, 4, 5]print(f'list1的类型: {type(list1)}')  # <class 'list'>
​# 2. 回顾: 字典推导式.dict1 = {i: i ** 2 for i in range(1, 6)}print(f'dict1: {dict1}')print(f'dict1的类型: {type(dict1)}')  # <class 'dict'>
​# 3. 回顾: 集合推导式.set1 = {i for i in range(1, 6)}print(f'set1: {set1}')print(f'set1的类型: {type(set1)}')    # <class 'set'>print('-' * 21)
​# 4. 尝试写1个"元组推导式", 注意: 没有元组推导式这个说法, 它的底层是: 生成器对象.# 生成器写法1: 推导式写法.my_generator = (i for i in range(1, 6))print(f'my_generator: {my_generator}')            # 地址值print(f'my_generator的类型: {type(my_generator)}') # <class 'generator'>print('-' * 21)
​# 5. 生成器不是一下子生成所有的数据, 而是用一个再生成1个.# 问: 如何从生成器中获取数据呢?# 答: 1: next()函数.   2.for循环遍历.# 方式1: next()函数, 从生成器中获取数据.print(next(my_generator))print(next(my_generator))print(next(my_generator))print(next(my_generator))print(next(my_generator))# print(next(my_generator))   # 报错: StopIteration, 停止迭代print('-' * 21)
​# 方式2: for循环遍历, 获取生成器的数据# 细节: next()是移动指针的, 获取下个元素, 如果不注释上边的代码, 这里打印结果是 空.for i in my_generator:print(i)
​
​

yield

方式2:yield关键字

# 需求: 获取 1 ~ 10之间的整数, 生成器写法.
# 1. 定义函数, 获取: 生成器对象.
def get_generator():# 回顾: list写法# list_data = []# for i in range(1, 11):#     list_data.append(i)# return list_data      # 返回列表对象
​# 对比: yield写法, 效果类似于上边的代码, 只不过返回的是: 生成器对象.for i in range(1, 11):yield i   # yield的作用: 1.创建生成器对象.  2.逐个的把每个元素放到生成器对象中.  3.函数结束时, 返回生成器对象.
​
​
# 2. 测试上述的函数.
if __name__ == '__main__':# 3. 调用函数, 获取生成器对象.my_generator = get_generator()print(type(my_generator))       # <class 'generator'>
​# 4. 从生成器对象中, 获取数据.# 方式1: next()函数print(next(my_generator))   # 1print(next(my_generator))   # 2print(next(my_generator))   # 3print('-' * 21)
​# 方式2: 遍历.for i in my_generator:print(i)
​

案例

分批次读取数据

需求:

自定义数据迭代器, 按照指定的条数生成批次数据, 为后续的AI模型训练课做准备.未来我们训练模型的时候, 是把数据分批次喂给模型的, 而不是一次性喂养.

# 分批加载数据
def data_loader(batch_size):with open('./jaychou_lyrics.txt', 'r', encoding='utf-8') as f:data = f.readlines()# 根据批次的数据量, 遍历批次, # 批次数 = (数据总条数 + 每批次的数据条数 -1) // 每批次的数据条数for i in range((len(data) + batch_size - 1) // batch_size):yield data[i * batch_size: i * batch_size + batch_size]
​
​
if __name__ == '__main__':data = data_loader(8)print(next(data))
import math
​
​
# 案例1: 扩展 math#ceil()函数, 获取天花板数, 即: 比这个数字大的所有整数中, 最小的那个整数.
# 总条数: 100条,  8条/批次, 问: 共多少批次?  13批
# print(math.ceil(5.0))   # 5
# print(math.ceil(5.1))   # 6
# print(math.ceil(5.6))   # 6
# print(math.ceil(21.6))  # 22
# print(math.ceil(100 / 8))   # 13
​
​
# 案例2: 定义函数 dataset_loader(batch_size), 用于获取: 批次数据.
def dataset_loader(batch_size):"""自定义的函数, 获取批次数据的.:param batch_size: 每批次数据的条数.:return: 生成器对象, 每个数据 = 1批的数据"""# 1. 读取源文件, 获取到所有的数据.with open('./data/jaychou_lyrics.txt', 'r', encoding='utf-8') as src_f:# 一次性读取所有的行, 并放到列表中.list_data = src_f.readlines()  # 数据格式: ['第1行\n', '第2行\n', '第3行\n'...]# 2. 获取数据的总条数.line_count = len(list_data)# 3. 根据数据的总条数, 结合每批次的数据条数, 计算: 总批次数.batch_count = math.ceil(line_count / batch_size)# 4. 遍历 总批次数, 获取到: 每个批次的 编号, 然后生成: 该批次的数据.for batch_idx in range(batch_count):"""推理过程:假设 batch_size = 8, batch_count = 13, 即: 13批, 8条/批, 则:batch_idx = 0, 代表第1批数据, 数据为: 第1条 ~ 第8条, 索引为: [0:8]batch_idx = 1, 代表第2批数据, 数据为: 第9条 ~ 第16条, 索引为: [8:16]batch_idx = 2, 代表第3批数据, 数据为: 第17条 ~ 第24条, 索引为: [16:24]......"""yield list_data[batch_idx * batch_size: batch_idx * batch_size + batch_size]
​
​
# 在main函数中测试.
if __name__ == '__main__':# 5. 获取生成器对象.data_loader = dataset_loader(batch_size=8)# 6. 获取第1批次的数据.# print(next(data_loader))batch_data1 = next(data_loader)# 具体的获取第1批次中每条数据的过程.for line in batch_data1:print(line, end='')print('-' * 21)
​# 7. 获取第2批次的数据.print(next(data_loader))

三. property

介绍

概述:

它是用来修饰函数的, 修饰之后, 可以把函数 当做 变量来使用.

目的/作用:

简化开发, 提高效率.

充当装饰器

property充当装饰器的具体用法 1. 在 获取值的函数上, 加上 @property

  1. 在 设置值的函数上, 加上 @方法名.setter,

    注意: 这里的方法名是@property修饰的方法名

3. 之后就可以把 函数 当做 变量来直接使用了.

格式1

获取与修改函数不同名

# 需求: 定义学生类, 有个私有的属性name, 提供公共的访问方式, 并测试.
# 1. 定义学生类.
class Student:# 2. 私有属性.def __init__(self):self.__name = '张三'      # 私有属性.
​# 3. 获取值的方法.# @property# def get_name(self):#     return self.__name## # 4. 设置值的方法.# @get_name.setter# def set_name(self, name):#     self.__name = name
​# 5. get_xxx(), set_xxx()函数 如果结合 property装饰器用, 具体写法如下:# 获取值的方法@propertydef name(self):return self.__name
​# 设置值的方法.@name.setterdef name(self, name):# 根据需求, 可以对传入的值做校验.# if name == '段誉':#     print('名字不能为段誉')# else:#     self.__name = name
​# 直接赋值.self.__name = name
​
# 在main中测试.
if __name__ == '__main__':# 6. 创建学生对象.s = Student()
​# 7. 访问Student类的私有属性name# print(s.name)       # 报错# print(s.__name)     # 报错.# s.set_name('乔峰')# print(s.get_name())
​# 8. 访问Student类的私有属性name# s.set_name = '虚竹'# print(s.get_name)
​# 看起来调用的是"属性", 其实底层是: 函数.s.name = '段誉'print(s.name)

格式2

获取与修改函数同名

# 定义学生类
class Student(object):# 定义私有属性def __init__(self):self.__name = '张三'
​# # 定义函数访问私有属性# def get_name(self):#     return self.__name## # 定义函数修改私有属性# def set_name(self, name):#     self.__name = name
​# 使用property定义函数变量@propertydef name(self):return self.__name
​@name.setterdef name(self, name):# 可以增加校验, 具体看需求# if name == '李四':#     print(f'name不能为{name}')# else:#     self.__name = nameself.__name = name
​
​
if __name__ == '__main__':s = Student()s.name = '李四'print(s.name)

充当类属性

property充当 类属性 的具体用法

  1. 直接在类中编写 类变量名 = property(获取值的方法名, 设置值方法名)

  2. 之后就可以通过 类名.类变量名的方式 来使用了, 这个是充当: 类量的.

  3. 如果要精准的修改或者获取某个学生的信息, 可以通过 对象名.性名的方式调用.

演示

# 需求: 定义学生类, 有个私有的属性name, 提供公共的访问方式, 并测试.
# 1. 定义学生类.
class Student:# 2. 私有属性.def __init__(self):self.__name = '张三'  # 私有属性.
​# 3. 获取值的方法.def get_name(self):return self.__name
​# 4. 设置值的方法.def set_name(self, name):self.__name = name
​# 5. property充当类属性的用法.# 参1: 获取值的函数.# 参2: 设置值的函数.# 注意: 顺序不要写反了, 这个是固定的顺序, 写反了会报错.name = property(get_name, set_name)
​
​
# 在main中测试.
if __name__ == '__main__':# 6. 创建学生对象.s = Student()s.name = '乔峰'  # 对象属性# Student.name = '乔峰' # 类属性print(s.name)print('-' * 21)
​# 7. 再次创建学生对象.s2 = Student()print(s2.name)



四. 正则

概述

正确的, 符合特定规则的 字符串. 英文名叫: Regular Expression,

简称叫: re, RegExp

作用

主要用于 校验数据.

细节

  1. 学正则, 主要是学正则的规则. 即: 哪个符号表示什么含义.

  2. 关于正则, 要求很简单, 只要能用我们讲的规则, 看懂别人写的 式子, 且能简单修改即可, 无需你手动编写.

  3. 到目前为止, 正则已经经历了N长的时间, 几乎你遇到的绝大多数的正则校验, 前辈们都已经写过了(帮我们写好了).

  4. 正则不独属于Python, 例如: Java, C#, JavaScript, Go...等众多的语言都支持, 且: 正则的规则都是一样的.

python中正则的调用

步骤

  1. 导包import re

  2. 正则匹配校验.result = re.match(正则规则, 要被校验的字符串, 扩展选项-例如区分大小写, 空值过滤...) 全词匹配, 从左往右依次匹配result = re.search(正则规则, 要被校验的字符串, 扩展选项-例如区分大小写, 空值过滤...) 分段批次, 任意一段能匹配即可.result = re.compile(...).sub(...) 用于做替换的

  3. 获取匹配到的数据.result.group()

演示

入门
# 需求1: 正则表达式入门.
# 导包
import re
​
# 校验字符串是否是 任意字符 + it + 任意字符.
result = re.match('.it.', 'aitb')   # 可以匹配
result = re.match('.it.', 'ait\n')  # 未匹配
result = re.match('.it.', 'ait')    # 未匹配
​
# 获取到匹配的结果.
if result:# 走这里, 有值, 获取到匹配的数据, 打印即可.print(result.group())
else:# 走这里, 没有匹配到数据, 打印即可.print('未匹配到!')
​
print('-' * 21)
替换

案例: 演示 正则替换, 即: 把符合正则规则的内容, 用指定的内容来替换.

格式: import re re.compile(正则规则).sub(新字符串, 旧字符串) 去旧字符串中, 找到符合正则规则的内容, 用新字符串来替换.

上述格式的语法糖: re.sub(正则规则, 新字符串, 旧字符串) 去旧字符串中, 找到符合正则规则的内容, 用新字符串来替换.

回顾: 字符串的 replace()函数, 也是替换的, 但是不支持正则. 快捷键: alt + enter: 给出建议的意思.

import re
​
if __name__ == '__main__':# 案例1: 把下述的符合正则规则的内容, 用*来替换.# 1. 定义 旧字符串.old_str = '你可以这样: 桀1桀2桀, 哈3哈, 呵A呵, 嘿嘿, 嘻嘻, 略略略, 嘤嘤嘤...'# 2. 定义 正则规则(字符串形式)reg_exp = '桀|哈|呵|嘿|嘻'# 3. 把符合正则规则的内容, 用*来替换.# 分解版写法.# 3.1 获取正则对象.# re_obj = re.compile(reg_exp)# 3.2 具体的替换过程.# result = re_obj.sub('*', old_str)
​# 合并版写法,         正则规则       新内容     旧内容# result = re.compile(reg_exp).sub('*', old_str)
​# 上述格式的语法糖, 正则规则   新内容     旧内容result = re.sub(reg_exp, '*', old_str)
​# 4 打印结果print(result)print('-' * 21)
​# 案例2: 回顾字符串的replace()函数.s1 = '抽烟只抽煊赫门, 一生只爱一个人. 其他烟: 中华, 煊赫门, 天叶, 煊赫门...'# result = s1.replace('煊赫门', '*')     # 不写次数, 默认替换所有.# result = s1.replace('煊赫门', '*', 1)  # 只替换1次(个)result = s1.replace('煊赫门|中华|天叶', '*')print(f'result:  {result}')

常用规则

单字符
"""
涉及到的正则的规则:.           代表: 任意的1个字符, \n除外\.          代表: 1个普通的.  即: 取消.的特殊含义a           代表: 1个字符a[abc]       代表: a, b, c中任意的1个字符, 即: 要么a, 要么b, 要么c[^abc]      代表: 除了a,b,c外, 任意的1个字符\d          代表: 任意的1个整数, 等价于 [0-9]\D          代表: 任意的1个非整数, 等价于 [^0-9]\w          代表: 非特殊字符, 即: 大小写英文字符, 数字, _, 汉字\W          代表: 特殊字符, 即: \w 取反.\s          代表: 空白字符, 例如: 空格, \t...\S          代表: 非空白字符, 即: \s取反.
"""
# 导包
import re
​
# 在main中测试
if __name__ == '__main__':# 演示: .           代表: 任意的1个字符, \n除外result = re.match('it.', 'ita')     # itaresult = re.match('it.', 'it\t')    # it\tresult = re.match('it.', 'it\n')    # 未匹配
​# 演示: \.          代表: 1个普通的.  即: 取消.的特殊含义# 细节: 为了防止打印异常信息, 你可以写成: r'it\.'  或者 'it\\.'result = re.match('it\\.', 'ita')        # 未匹配result = re.match('it\\.', 'it.')        # it.result = re.match('it\\.', 'it.abc')     # it.
​# 演示: a           代表: 1个字符aresult = re.match('a', 'abc')            # aresult = re.match('a', 'xyz')            # 未匹配
​# 演示: [abc]      代表: a, b, c中任意的1个字符, 即: 要么a, 要么b, 要么cresult = re.match('it[abc]', 'itabc')    # itaresult = re.match('it[abc]', 'itbc')     # itbresult = re.match('it[abc]', 'itd')      # 未匹配
​# 演示: [^abc]      代表: 除了a,b,c外, 任意的1个字符result = re.match('it[^abc]', 'itabc')  # 未匹配result = re.match('it[^abc]', 'itbc')   # 未匹配result = re.match('it[^abc]', 'itd')    # itd
​# 演示: \d          代表: 任意的1个整数, 等价于 [0-9]result = re.match('hm[0-9]', 'hm1')     # hm1result = re.match('hm[0-9]', 'hm3a')    # hm3result = re.match(r'hm\d', 'hm3a')      # hm3result = re.match(r'hm\d', 'hma')      # 未匹配
​# 演示: \D          代表: 任意的1个非整数, 等价于 [^0-9]result = re.match(r'hm\D', 'hma')   # hmaresult = re.match(r'hm\D', 'hm3a')  # 未匹配
​# 演示: \w          代表: 非特殊字符, 即: 大小写英文字符, 数字, _, 汉字result = re.match(r'hm\w', 'hma')  # hmaresult = re.match(r'hm\w', 'hmB')  # hmBresult = re.match(r'hm\w', 'hm1')  # hm1result = re.match(r'hm\w', 'hm_')  # hm_result = re.match(r'hm\w', 'hm!')  # 未匹配
​# 演示: \W          代表: 特殊字符, 即: \w 取反.result = re.match(r'hm\W', 'hm!')  # hm!result = re.match(r'hm\W', 'hm_')  # 未匹配
​# 演示: \s          代表: 空白字符, 例如: 空格, \t...result = re.match(r'hm\s', 'hm')    # 未匹配result = re.match(r'hm\s', 'hm ')   # hmresult = re.match(r'hm\s', 'hm\t')  # hmresult = re.match(r'hm\s', 'hm\n')  # hm\nresult = re.match(r'hm\s', 'hma')   # 未匹配
​# 演示: \S          代表: 非空白字符, 即: \s取反.# 自己测试.
​# 打印校验到的数据.if result:print(f'匹配到: {result.group()}')else:print('未匹配!')

多字符
"""
涉及到的正则的规则如下, 都是和 数量词 有关:?           代表: 前边的内容, 出现0次 或者 1次*           代表: 前边的内容, 至少出现0次, 至多出现n次(无数次)+           代表: 前边的内容, 出现1次 或者 多次.a{n}        代表: a恰好出现n次, 多一次少一次都不行.a{n,}       代表: a至少出现n次, 至多无所谓.a{n,m}      代表: a至少出现n次, 至多出现m次, 包括n 和 m
"""
# 导包
import re
​
# main中测试
if __name__ == '__main__':# 演示: ?           代表: 前边的内容, 出现0次 或者 1次result = re.match('it.?', 'it')result = re.match('it.?', 'it ')result = re.match('it.?', 'itabcABC')result = re.match('it.?', 'it\nABC')    # it
​# 演示: *           代表: 前边的内容, 至少出现0次, 至多出现n次(无数次)result = re.match('it[abc]*', 'it\nABC')  # itresult = re.match('it[abc]*', 'itabcABC') # itabcresult = re.match('it[abc]*', 'it ')      # itresult = re.match('it[abc]*', 'it')       # it
​# 演示: +           代表: 前边的内容, 出现1次 或者 多次.result = re.match('it[abc]+', 'it')   # 未匹配result = re.match('it[abc]+', 'it ')  # 未匹配result = re.match('it[abc]+', 'it\nABC')  # 未匹配result = re.match('it[abc]+', 'itabcABC')  # itabc
​# 演示: a{n}        代表: a恰好出现n次, 多一次少一次都不行.result = re.match('it[abc]{2}', 'itabcABC')  # itabresult = re.match('it[abc]{2}', 'itacb')     # itacresult = re.match('it[abc]{2}', 'ita')       # 未匹配
​# 演示: a{n,}       代表: a至少出现n次, 至多无所谓.result = re.match('it[abc]{2,}', 'ita')         # 未匹配result = re.match('it[abc]{2,}', 'itacb')       # itacbresult = re.match('it[abc]{2,}', 'itabcABC')    # itabc
​# 演示: a{n,m}      代表: a至少出现n次, 至多出现m次, 包括n 和 mresult = re.match('it[abc]{2,3}', 'itabcde')     # itabcresult = re.match('it[abc]{2,3}', 'ita')         # 未匹配
​
​# 打印结果.print(f'匹配到: {result.group()}' if result else '未匹配!')

开始和结束
"""
^   代表开头
$   代表结尾
"""
import re
​
if __name__ == '__main__':# 演示: ^       代表: 正则表达式的 开头# 需求: 校验字符串必须以 it 开头.result = re.match(r'it\d', 'it123')      # it1result = re.match(r'it\d', '1it123')     # 未匹配!
​result = re.search(r'it\d', 'it123')   # it1result = re.search(r'it\d', '1it123')  # it1
​# ^代表开头, 即: 如下的代码其实是 全词匹配, 必须从字符串的第1个字符开始校验.result = re.search(r'^it\d', '1it123')  # 未匹配!
​# 演示: $       代表: 正则表达式的 结尾# 需求: 校验字符串必须以 数字 结尾.result = re.match(r'it\d', 'it123a')      # it1result = re.match(r'it\d$', 'it123a')     # 未匹配!
​# 扩展: 校验手机号.# 规则: 1. 必须以1开头.   2.第2位数字可以是3 ~ 9.  3.必须是纯数字.  4.长度必须是11位.result = re.match(r'^1[3-9]\d{9}$', '13112345678a')result = re.match(r'^1[3-9]\d{9}$', '13112345678')
​# 打印匹配到的结果.print(result.group()  if result else '未匹配!')

分组
"""
|       代表: 或者的意思
()      代表: 分组
\num    代表: 获取第num组的内容
扩展:(?P<分组名>)   设置分组(?P=分组名)    获取指定分组的内容
​
细节:正则默认属于第0组, 之后就按照 左小括号来数, 是第几个, 就是第几组.
"""

import re
​
if __name__ == '__main__':# 需求1: 在列表中, 打印用户喜欢吃 和 不喜欢吃的水果.# 1. 定义水果列表.fruits = ['apple', 'banana', 'orange', 'pear']# 2. 遍历, 获取每种水果.for fruit in fruits:# 3. 假设用户喜欢吃 香蕉, 梨, 判断即可.result = re.match('banana|pear', fruit)# 4. 打印结果.if result:print(f'喜欢吃: {fruit}')else:print(f'不喜欢吃: {fruit}')

分组(验证邮箱案例)

import re
​
if __name__ == '__main__':# 需求: 匹配出 163, 126, qq等邮箱.# 邮箱规则: 前边是4 ~ 20位的字母, 数字, 下划线 + @标记符 + 域名# 1. 定义邮箱字符串.email_str = 'zhangsan@163com'email_str = 'zhangsan@1634.com'email_str = 'zh@qq.com'email_str = 'zhangsan@163.com'
​# 2. 定义 校验邮箱的 正则表达式.pattern = r'^[a-zA-Z0-9_]{4,20}@(163|126|qq)\.com$'# 3. 校验邮箱.result = re.match(pattern, email_str)# 4. 打印结果.if result:print(f'匹配到: {result.group()}')     # zhangsan@163.com, 等价于 result.group(0), 即: 获取所有匹配到的数据print(f'匹配到: {result.group(0)}')    # zhangsan@163.com, 效果同上.print(f'匹配到: {result.group(1)}')    # 163else:print('未匹配!')

提取指定分组

import re
​
if __name__ == '__main__':# 需求: 匹配 qq:qq号 这样的数据, 提取出 qq文字 和 qq号码.# 1. 定义字符串.s1 = "qq:1234567"
​# 2. 匹配数据.result = re.match(r'(qq):(\d{6,11})', s1)
​# 3. 打印匹配到的数据.if result:print(f'匹配到: {result.group()}')     # qq:1234567print(f'匹配到: {result.group(0)}')    # qq:1234567print(f'匹配到: {result.group(1)}')    # qqprint(f'匹配到: {result.group(2)}')    # 1234567else:print('未匹配!')
分组后起别名

引用指定分组

import re
​
if __name__ == '__main__':# 需求1: 正则校验 html标签, 简单版.# 1. 定义html标签字符串.html_str1 = '<html>AI就业21期</html>'
​# 2. 正则校验.# 假设: 标签规则: 2到4位字母result = re.match('<[a-zA-Z]{2,4}>.*</[a-zA-Z]{2,4}>', html_str1)
​# 上述格式优化版, 加入: 分组思想.result = re.match(r'<([a-zA-Z]{2,4})>.*</\1>', html_str1)
​# 3. 打印匹配结果.if result:print(f'匹配到: {result.group()}')else:print('未匹配!')
​print('-' * 21)
​# 需求2: 正则校验 html标签, 升级版.# 假设: 外部标签规则 2到4位字母,  内部标签规则: h + 1到6的数字# 1. 定义html标签字符串.html_str2 = '<html><h1>AI就业21期</h1></html>'
​# 2. 正则校验result = re.match(r'<[a-zA-Z]{2,4}><h[1-6]>.*</h[1-6]></[a-zA-Z]{2,4}>', html_str2)# 加入分组, 优化上述的代码.result = re.match(r'<([a-zA-Z]{2,4})><(h[1-6])>.*</\2></\1>', html_str2)
​# 扩展: 给分组设置组名.result = re.match(r'<(?P<A>[a-zA-Z]{2,4})><(?P<B>h[1-6])>.*</(?P=B)></(?P=A)>', html_str2)
​# 3. 打印匹配结果.if result:print(f'匹配到: {result.group()}')else:print('未匹配!')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/53336.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Centos】绕开报错ModuleNotFoundError: No module named ‘dnf‘

问题原因&#xff1a; 安装python3.9后不能使用yum Traceback (most recent call last):File "/usr/bin/yum", line 57, in <module>from dnf.cli import main ModuleNotFoundError: No module named dnf绕开yum解决方法&#xff1a; 直接下载相关依赖包 htt…

怎样将手机屏幕(远程)投屏到家里的大电视上?

我不住家里&#xff0c;前几次回去都会替老爸老妈清理手机。这两个星期没空回去&#xff0c;老爸吐槽手机用几天就又卡了&#xff0c;其实就是清理一些手机缓存的问题。 我说我远程控制他的手机&#xff0c;给他清理一下。他一听“控制”就不喜欢&#xff0c;说我大了&#xf…

软件测试面试从哪方面面试?

一、面试基础题 简述测试流程: 什么是软件测试&#xff1f;软件测试的目的与原则 问&#xff1a;软件生存周期及其模型是什么&#xff1f; 什么是软件质量&#xff1f; 自动化测试脚本开发的主要步骤: 目前主要的测试用例设计方法是什么&#xff1f; 常见的测试用例设计…

【Python知识宝库】文件操作:读写文件的最佳实践

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 前言一、文件读取1. 使用open函数2. 逐行读取3. 使用readlines和readline 二、文件写入1. 写入文本2. 追加内容3. 写入…

使用shell脚本安装mysql8,进行主从备份配置

思路 在3台主机上安装mysql进行主从备份配置 使用rpm包yum安装mysql 首先&#xff0c;我们要准备好安装文件&#xff0c;首先下载rpm包 wget -P "/opt/" https://repo.mysql.com//mysql80-community-release-el7-3.noarch.rpm 然后执行安装&#xff08;默认已配置…

HMI设计:嵌入式设备和电脑的差异化,工控领域首选。

嵌入式设备属于专机专用&#xff0c;电脑是通用&#xff0c;从性能、用途、特殊能力、成本、通信上嵌入式设备完全优于电脑&#xff0c;是工控领域的首选。 嵌入式设备和电脑在很多方面有着显著的差异&#xff0c;主要体现在以下几个方面&#xff1a; 1. 设计用途&#xff1a…

go 开发小技巧

一、简介 本篇文章会介绍go 开发小技巧。 二、go 开发技巧 2.1 Semaphore type Semaphore chan struct{}func NewSemaphore(maxCount int) Semaphore {return make(chan struct{}, maxCount) }func (s Semaphore) Acquire() {s <- struct{}{} }func (s Semaphore) tryAcq…

在js渲染的dom中的事件中传递对象

在某些情况下&#xff0c;可能需要将整个对象或部分对象嵌入到 HTML 元素的属性中&#xff0c;可以将对象数据序列化为 JSON 字符串&#xff0c;存储在 data-* 自定义属性中。这样可以在事件中取出并解析对象数据&#xff1a; <!DOCTYPE html> <html lang"en&qu…

linux高级学习9

24.9.6学习目录 一.共享内存1.共享内存的API 一.共享内存 特点&#xff1a; 其在进程间共享数据的方法中是最快的要注意对给定存储区访问时进行互斥 1.共享内存的API &#xff08;1&#xff09;获取共享内存标识符 在shell中使用 ipcs -m进行查看共享内存 ipcrm -m shmid删…

P1546 [USACO3.1] 最短网络 Agri-Net

[题目通道]([USACO3.1] 最短网络 Agri-Net - 洛谷) #include<bits/stdc.h> #define int long long using namespace std; const int N1e6100; struct edge{int u,v,w; }e[N*30]; bool cmp(edge a,edge b){return a.w<b.w; } int a,b,c,n,m,fa[N],cnt0,ans0; int fin…

目标检测-YOLOv10

YOLOv10 是 YOLO 系列的最新版本&#xff0c;进一步推动了目标检测技术的发展。它在前代&#xff08;YOLOv9&#xff09;的基础上进行了更多优化和改进&#xff0c;使得模型在复杂场景、实时性以及精度方面取得了更高的突破。YOLOv10 将高效的架构设计与新颖的技术结合&#xf…

C++万字解读类和对象(上)

1.类的定义 class为定义类的关键字&#xff0c;Stack为类的名字&#xff0c;{}中为类的主体&#xff0c;注意类定义结束时后面分号不能省略。类体中内容称为类的成员&#xff1a;类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。 为了区分成员变量&…

[QT] QT事件与事件重写

一.事件 事件(event)是由系统或者 Qt本身在不同的场景下发出的。当用户按下鼠标、敲下键盘&#xff0c;或者是窗口关闭等都会发出一个相应的事件。 一些事件在用户操作时发出(如鼠标/键盘事件); 另一些事件则是由系统自动发出(如计时器事件)。 Qt窗口中对于产生的一系列事件都…

MarkdownEditor 配置以及使用

MarkdownEditor 配置以及使用 MarkdownEditor是一款基于浏览器的 Markdown 编辑器&#xff0c;虽然他是独立软件&#xff0c;但该软件内嵌一个浏览器。功能非常简单实用、反应速度很快&#xff0c;号称是Markdown领域的NotePad&#xff08;记事本&#xff09;。 MarkdownEdit…

PHP与Nginx配置优化:深入探讨Socket通信

在现代Web开发中&#xff0c;PHP和Nginx的组合是一种常见且高效的服务器配置。本文将深入探讨PHP-FPM&#xff08;FastCGI进程管理器&#xff09;与Nginx的配置&#xff0c;特别是关于它们之间的通信方式——Unix Domain Socket和TCP Socket的选择与优化。 PHP-FPM配置解析 首…

计网名词解释

DNS的主要功能和特点 域名解析&#xff1a;DNS的核心功能是将用户输入的域名解析为IP地址。因为计算机之间只能通过IP地址进行通信&#xff0c;而域名更易于人类记忆和使用&#xff0c;所以DNS起到了桥梁的作用。 分布式数据库&#xff1a;DNS是一个分布式的数据库系统&#x…

Vue3 父子传参 简单易懂

在Vue 3中&#xff0c;父组件向子组件传递数据&#xff08;也称为“props”&#xff09;是一个非常常见的模式。这是通过props选项在子组件中定义的&#xff0c;然后在父组件的模板中使用该子组件时通过属性&#xff08;attributes&#xff09;传递数据。 步骤 1: 定义子组件的…

面向对象23种设计模式通俗理解

终点即是起点,自强不息! 设计模式的理解 设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 模式&#xff1a;在某些场景下&#xff0c;针对某类问题的某种通用的解决方案。 场景&#xff1a;项目所在的环境 问题&#xff1a;约束条件&#xff0c;项目目标…

vue3 项目中使用git

一.vue项目创建 二.创建本地仓库并和远程仓库进行绑定 在vue3-project-git 项目文件夹下 初始化一个新的Git仓库&#xff0c;可以看到初始化成功之后就会出现一个.git文件&#xff0c;该文件包含所有必要的 Git 配置和版本控制信息。 创建远程仓库: 打开gitee ,点击右上角 ‘…

MapSet之二叉搜索树

系列文章&#xff1a; 1. 先导片--Map&Set之二叉搜索树 2. Map&Set之相关概念 目录 前言 1.二叉搜索树 1.1 定义 1.2 操作-查找 1.3 操作-新增 1.4 操作-删除(难点) 1.5 总体实现代码 1.6 性能分析 前言 TreeMap 和 TreeSet 是 Java 中基于搜索树实现的 M…