0基础跟德姆(dom)一起学AI Python进阶08-生成器,property关键字,正则表达式

* 生成器
  * yield关键字
  * 生成批次数据
* property关键字的用法
  * 修饰方法
  * 修饰类变量
* 正则表达式
  * 正则表达式规则
  * match()
  * search()
  * compile()

---

 1.生成器入门

```python
"""
生成器介绍:
    概述:
        它指的是 generator, 类似于以前学过的: 列表推导式, 集合推导式, 字典推导式...
    作用:
        降低资源消耗, 快速(批量)生成数据.
    实现方式:
        1. 推导式写法.
        2. yield写法.
    问题: 如何从生成器对象中获取数据?
    答案:
        1. for循环遍历
        2. next()函数, 逐个获取.
"""

# 案例1: 回顾之前的列表推导式, 集合推导式.
# 需求: 生成 1 ~ 5 的数据.
my_list = [i for i in range(1, 6)]
print(my_list, type(my_list))   # [1, 2, 3, 4, 5] <class 'list'>

my_set = {i for i in range(1, 6)}
print(my_set, type(my_set))     # {1, 2, 3, 4, 5} <class 'set'>


# 案例2: 演示 生成器写法1, 推导式写法
# 尝试写一下, "元组"推导式, 发现打印的结果不是元组, 而是对象, 因为这种写法叫: 生成器.
my_tuple = (i for i in range(1, 6))

print(my_tuple)             # <generator object <genexpr> at 0x0000024C90F056D0>    生成器对象
print(type(my_tuple))       # <class 'generator'>       生成器类型
print('-' * 31)

# 案例3: 如何从生成器对象中获取数据呢?
# 1. 定义生成器, 获取 1 ~ 5的数字.
my_generator = (i for i in range(1, 6))

# 2. 从生成器中获取数据.
# 格式1: for循环遍历
for i in my_generator:
    print(i)

# 格式2: next()函数, 逐个获取.
print(next(my_generator))       # 1
print(next(my_generator))       # 2
```

2.yield关键字

```python
# 案例: 演示 yield关键字方式, 获取生成器.

# 需求: 自定义 get_generator()函数, 获取 包括: 1 ~ 5之间的整数 生成器.
# 1. 定义函数.
def get_generator():
    """
    用于演示 yield关键字的用法
    :return: 生成器对象.
    """
    # 思路1: 自定义列表, 添加指定元素, 并返回.
    # my_list = []
    # for i in range(1, 6):
    #     my_list.append(i)
    # return my_list

    # 思路2: yield写法, 即: 如下的代码, 效果同上.
    for i in range(1, 6):
        yield i     # yield会记录每个生成的数据, 然后逐个的放到生成器对象中, 最终返回生成器对象.


# 在main中测试.
if __name__ == '__main__':
    # 2. 调用函数, 获取生成器对象.
    my_generator = get_generator()

    # 3. 从生成器中获取每个元素.
    print(next(my_generator))   # 1
    print(next(my_generator))   # 2

    print('-' * 31)

    # 4. 遍历, 获取每个元素.
    for i in my_generator:
        print(i)
```

3.生成批次数据

```python
"""
案例: 用生成器生成批次数据, 给后续的AI课程做铺垫, 因为在模型训练中, 数据都是分批次来 "喂" 的.

需求: 读取项目下的  jaychou_lyrics.txt文件(其中有5000多条 歌词数据), 按照8个 / 批次, 获取生成器, 并从中获取数据.
"""

import math

# 需求1: 铺垫知识,  math.ceil(数字):  获取指定数字的天花板数(向上取整), 即: 比这个数字大的所有整数中, 最小的哪个整数.
# print(math.ceil(5.1))       # 6
# print(math.ceil(5.6))       # 6
# print(math.ceil(5.0))       # 5

# 需求2: 获取生成器对象, 从文件中读数据数据, n条 / 批次
# 1. 定义函数 dataset_loader(batch_size), 表示: 数据生成器, 按照 batch_size条 分批.
def dataset_loader(batch_size):     # 假设: batch_size = 8
    """
    该函数用于获取生成器对象, 每条数据都是一批次的数据. 即: 生成器(8条, 8条, 8条...)
    :param batch_size: 每批次有多少条数据
    :return: 返回生成器对象.
    """
    # 1.1 读取文件, 获取到每条(每行)数据.
    with open("./jaychou_lyrics.txt", 'r', encoding='utf-8') as f:
        # 一次读取所有行, 每行封装成字符串, 整体放到列表中.
        data_lines = f.readlines()      # 结果: [第一行, 第二行, 第三行...]

    # 1.2 根据上述的数据, 计算出: 数据的总条数(总行数), 假设: 100行(条)
    line_count = len(data_lines)

    # 1.3 基于上述的总条数 和 batch_size(每批次的条数), 获取: 批次总数(即: 总共多少批)
    batch_count = math.ceil(line_count / batch_size)        # 例如: math.ceil(100 / 8) = 13

    # 1.4 具体的获取每批次数据的动作, 用 yield包裹, 放到生成器中, 并最终返回生成器(对象)即可.
    for i in range(batch_count):        # batch_count的值: 13,  i的值: 0, 1, 2, 3, 4, 5, .... 12
        # 1.5 yield会记录每批次数据, 封装到生成器中, 并返回(生成器对象)
        """
            推理过程:
                i = 0, 代表第1批次数据, 想要 第 1 条   ~~~~  第 8 条数据,    即:  data_lines[0:8]      
                i = 1, 代表第2批次数据, 想要 第 9 条   ~~~~  第 16 条数据,   即:  data_lines[8:16]      
                i = 2, 代表第3批次数据, 想要 第 17 条   ~~~~  第 24 条数据,  即:  data_lines[16:24]
                ......      
        """
        yield data_lines[i * batch_size: i * batch_size + batch_size]

# 在main中, 测试调用
if __name__ == '__main__':
    # 2. 获取生成器对象.
    my_generator = dataset_loader(13)

    # 3. 从生成器中获取第 1 批数据.
    # print(next(my_generator))
    # # 从第一批次中, 获取具体的每一条数据.
    # for line in next(my_generator):
    #     print(line, end='')
    #
    # print('-' * 31)
    #
    # # 从第二批次中, 获取具体的每一条数据.
    # for line in next(my_generator):
    #     print(line, end='')
    # print('-' * 31)


    # 4. 查看具体的每一批数据.
    for batch_data in my_generator:
        print(batch_data)
```

4.property-充当装饰器用法

```python
"""
案例: 演示property关键字的 装饰器用法.

property解释:
    概述:
        它表示属性的意思, 可以用来修饰 方法, 修饰之后, 实现: 把 方法 当做 变量来使用.
    目的:
        简化开发.
    用法:
        格式1: 当做装饰器使用.
        格式2: 修饰类变量

    property充当装饰器用法, 格式:
        @property           # 修饰的是 获取值的函数.
        @方法名.setter       # 修饰的市 设置值的函数, 注意: 这里的方法名 要和 @property修饰的方法名保持一致.

    修饰类变量:
        类变量名 = property(get_xxx函数, set_xxx函数), 即: 参1是获取值的, 参2是设置值,  之后就可以直接使用该 类变量了.
"""

# 需求1: 定义Student类, 其中有个私有的属性 name, 定义公共的访问方式, 实现在外界访问该 私有变量.
# 1. 定义学生类.
class Student(object):
    # 1.1 定义私有变量(属性)
    def __init__(self):
        self.__name = '乔峰'      # 两个下划线_ 表示私有

    # # 1.2 定义get_xxx(), 获取: 姓名
    # @property
    # def get_name(self):
    #     return self.__name
    #
    # # 1.3 定义set_xxx(), 修改: 姓名
    # @get_name.setter
    # def set_name(self, name):
    #     self.__name = name

    # 1.2 定义get_xxx(), 获取: 姓名
    @property
    def name(self):
        return self.__name

    # 1.3 定义set_xxx(), 修改: 姓名
    @name.setter
    def name(self, name):
       self.__name = name


# 2. 在main函数中测试
if __name__ == '__main__':
    # 场景1: 以前学面向对象时的 普通写法.
    # # 2.1 创建学生类对象.
    # s = Student()
    # # 2.2 打印 name 属性值
    # print(s.get_name())
    # # 2.3 设置 name 属性值
    # s.set_name('萧峰')
    # # 2.4 打印 name 属性值
    # print(s.get_name())

    # 场景2: 演示: property充当装饰器后的用法.
    # # 2.1 创建学生类对象.
    # s = Student()
    # # 2.2 打印 name 属性值
    # print(s.get_name)
    # # 2.3 设置 name 属性值
    # s.set_name = '萧峰'
    # # 2.4 打印 name 属性值
    # print(s.get_name)

    # 场景3: 演示: property充当装饰器后的用法, 最终写法
    # 2.1 创建学生类对象.
    s = Student()
    # 2.2 打印 name 属性值
    print(s.name)
    # 2.3 设置 name 属性值
    s.name = '夯哥'
    # 2.4 打印 name 属性值
    print(s.name)
```

5.property-修饰类变量

```python
"""
案例: 演示property关键字的 修饰类属性的用法.

property解释:
    概述:
        它表示属性的意思, 可以用来修饰 方法, 修饰之后, 实现: 把 方法 当做 变量来使用.
    目的:
        简化开发.
    用法:
        格式1: 当做装饰器使用.
        格式2: 修饰类变量

    property充当装饰器用法, 格式:
        @property           # 修饰的是 获取值的函数.
        @方法名.setter       # 修饰的市 设置值的函数, 注意: 这里的方法名 要和 @property修饰的方法名保持一致.

    修饰类变量:
        类变量名 = property(get_xxx函数, set_xxx函数), 即: 参1是获取值的, 参2是设置值,  之后就可以直接使用该 类变量了.
"""

# 需求1: 定义Student类, 其中有个私有的属性 name, 定义公共的访问方式, 实现在外界访问该 私有变量.
# 1. 定义学生类.
class Student(object):
    # 1.1 定义私有变量(属性)
    def __init__(self):
        self.__name = '乔峰'      # 两个下划线_ 表示私有

    # 1.2 定义get_xxx(), 获取: 姓名
    def get_name(self):
        return self.__name

    # 1.3 定义set_xxx(), 修改: 姓名
    def set_name(self, name):
       self.__name = name

    # 1.4. 通过property关键字, 实现: 把 get_name() 和 set_name()函数, 封装成 类属性.
    # 格式: 类变量名 = property(get_xxx函数, set_xxx函数), 即: 参1是获取值的, 参2是设置值,  之后就可以直接使用该 类变量了.
    name = property(get_name, set_name)

# 2. 在main函数中测试
if __name__ == '__main__':
    # 演示: property修饰 类属性的用法.
    # 2.1 创建学生类对象.
    s = Student()
    # 2.2 打印 name 属性值
    print(s.name)
    # 2.3 设置 name 属性值
    s.name = '夯哥'
    # 2.4 打印 name 属性值
    print(s.name)       # s1.name
```

6.正则表达式介绍

```python
"""
正则表达式介绍:
    概述:
        全称是 Regular Expression, 正则表达式, 即: 正确的, 符合特定规则的式子.
    作用:
        校验, 匹配数据的.
    细节:
        1. 学正则就是学正则表达式的 规则, 不要背, 因为这么多年了, 校验邮箱, 校验手机...等一些列的规则前辈们都写出来, 网上一搜一堆.
        2. 我讲正则的目的: 能用我们学的规则, 看懂别人写的 (正则表达式)式子, 且会根据需求修改即可.
        3. 正则不独属于任意的一门语言, Java, Python...都支持, 且: 正则规则都是一样的, 不同的是 写法不一样.

    Python中 正则的使用步骤:
        1. 导包
            import re
        2. 正则校验.
            re.match()
            re.search()
            re.compile().sub()
        3. 获取匹配结果.
            result = re.group()
    我们要学习的正则规则如下:
        .
        \.
        [abc]
        [^abc]
        \d
        \D
        \s
        \S
        \w
        \W

        ^
        $

        ?
        +
        *
        {n}
        {n,}
        {n,m}

        |
        ()
        \num

        扩展:
            (?P<分组名>)       给分组起名字
            (?P=分组名)        使用指定分组的内容
"""
```

7.正则表达式-match和search函数

```python
"""
正则表达式介绍:
    概述:
        全称是 Regular Expression, 正则表达式, 即: 正确的, 符合特定规则的式子.
    作用:
        校验, 匹配数据的.
    细节:
        1. 学正则就是学正则表达式的 规则, 不要背, 因为这么多年了, 校验邮箱, 校验手机...等一些列的规则前辈们都写出来, 网上一搜一堆.
        2. 我讲正则的目的: 能用我们学的规则, 看懂别人写的 (正则表达式)式子, 且会根据需求修改即可.
        3. 正则不独属于任意的一门语言, Java, Python...都支持, 且: 正则规则都是一样的, 不同的是 写法不一样.

    Python中 正则的使用步骤:
        1. 导包
            import re
        2. 正则校验.
            re.match(pattern=正则表达式, str, flag)       参1: 正则表达式,  参2: 要校验的字符串, 参3:可选项, 例如: 忽略大小写, 多行模式等.
            re.search(pattern=正则表达式, str, flag)
            re.compile(正则表达式).sub(用来替换的内容, 要被替换的内容)
        3. 获取匹配结果.
            result = re.group()
    上述函数 介绍:
        match:  匹配的意思, 从左往右, 逐个字符进行匹配, 不会跳过任意的1个字符, 要求: 全部匹配才行.
        search: 查找的意思, 从左往右, 从任意的某个字符开始, 只要能匹配上即可.
        compile: 用于替换的.

    我们要学习的正则规则如下:
        .           代表: 任意的1个字符
        \.          取消.的特殊含义, 就是一个普通的. 校验邮箱的时候用, 例如: zhangsan@163.com
        a           代表: 就是1个普通的字符a
        [abc]
        [^abc]
        \d
        \D
        \s
        \S
        \w
        \W

        ^
        $

        ?
        +
        *           数量词, 代表前边的内容, 至少出现 0次, 至多出现 n次
        {n}
        {n,}
        {n,m}

        |
        ()
        \num

        扩展:
            (?P<分组名>)       给分组起名字
            (?P=分组名)        使用指定分组的内容
"""
import re

# 需求2: 校验字符串格式是否是  任意1个字符 + it + 任意的1个字符
# result = re.match('.it.', '1ita')     # .it. 意思是: 任意1个字符 + it + 任意的1个字符
# result = re.match('.it.', 'ita')     # .it. 意思是: 任意1个字符 + it + 任意的1个字符

# 需求2: 校验字符串是否包含 it
# match: 从左往右, 逐个字符进行匹配, 不会跳过任意的1个字符, 要求: 全部匹配才行.
# result = re.match('.*it.*', 'sdit123sf')
# result = re.match('.*it.*', 'it123sf')
# result = re.match('.*it.*', 'sdit')

# it.*   it + 后续任意内容.
# result = re.match('it.*', 'sdit123sf'

# search: 查找的意思, 从左往右, 从任意的某个字符开始, 只要能匹配上即可.
result = re.search('it.*', 'sdit 123sf')


# 打印结果
if result:          # 只要result不是None, 就会走这里.
    # print(result)   # 匹配到的正则对象
    print(result.group())       # 从正则中, 获取具体 匹配到的内容.
else:
    # print(result)   # None
    print('未匹配!')
```

8.compile函数

```python
"""
案例: 演示正则 替换.

涉及到的 re 模块下的函数:
    写法1:
        re.compile(正则表达式).sub(用来替换的内容, 要被替换的内容)

    写法2: 即, 上述格式的语法糖.
        re.sub(正则表达式, 用来替换的内容, 要被替换的内容)

     回顾: 字符串中的replace()函数, 也可以替换, 但是是全词匹配, 不支持正则.
        字符串.replace(旧内容, 新内容)
"""
import re

# 扩展: r'字符串'   取消字符串中\的转移的含义, 就是1个普通的\
# print('d:\\aa\\bb\\cc')     # d:\aa\bb\cc,  \在python中有特殊含义(转移符), 两个\表示一个\
# print(r'd:\\aa\\bb\\cc')    # d:\\aa\\bb\\cc
# print(r'd:\aa\bb\cc')    # d:\\aa\\bb\\cc

# 需求1: 把字符串中的"敏感词" 给 替换成 *
old_str = "车主说: 你的刹车片应该换了啊, 嘿嘿"

# 1. 自定义正则规则.
p = r'啊|阿|嘿|呵|哈|啦|嘻|桀'        # pattern: 模板(可以理解为: 正则规则),  字符串前加r表示, 取消转移.

# 2. 基于正则规则, 获取正则对象.
res = re.compile(pattern=p)     # pattern=具体的正则字符串

# 3. 对上述的字符串进行替换.
result = res.sub('A', old_str)  # 返回的是: 字符串.

# 4. 打印匹配结果.
if result:
    print(f'匹配到: {result}')
else:
    print('未匹配!')

print('-' * 31)

# 需求2: 上述代码的简化版, 语法糖实现
old_str = "故人西辞黄鹤楼, 烟花三月黄鹤楼, 中华虽然好抽, 但是不要上瘾, 抽烟只抽煊赫门, 一生只爱一个人!"
# 参1: 正则表达式.
# 参2: 用来替换的字符串.
# 参3: 要被替换的字符串.
result = re.sub('黄鹤楼|中华|煊赫门', '*', old_str)
print(result)
print('-' * 31)

# 需求3: 回顾字符串的 replace()
s1 = "烟花三月黄鹤楼, 黄鹤楼虽然好抽, 大中华, 抽着黄鹤楼!"

# 参1: 旧字符串(要被替换的)  参2: 新字符串(用来替换的)  参3: 替换几个, 不写就替换所有.
result = s1.replace('黄鹤楼', '*', 2)
# result = s1.replace('黄鹤楼|中华', '*', 2)  # 无效, 不支持正则.
print(result)
```

9.正则-匹配单个字符

```python
"""
正则表达式介绍:
    概述:
        全称是 Regular Expression, 正则表达式, 即: 正确的, 符合特定规则的式子.
    作用:
        校验, 匹配数据的.
    细节:
        1. 学正则就是学正则表达式的 规则, 不要背, 因为这么多年了, 校验邮箱, 校验手机...等一些列的规则前辈们都写出来, 网上一搜一堆.
        2. 我讲正则的目的: 能用我们学的规则, 看懂别人写的 (正则表达式)式子, 且会根据需求修改即可.
        3. 正则不独属于任意的一门语言, Java, Python...都支持, 且: 正则规则都是一样的, 不同的是 写法不一样.

    Python中 正则的使用步骤:
        1. 导包
            import re
        2. 正则校验.
            re.match(pattern=正则表达式, str, flag)       参1: 正则表达式,  参2: 要校验的字符串, 参3:可选项, 例如: 忽略大小写, 多行模式等.
            re.search(pattern=正则表达式, str, flag)
            re.compile(正则表达式).sub(用来替换的内容, 要被替换的内容)
        3. 获取匹配结果.
            result = re.group()
    上述函数 介绍:
        match:  匹配的意思, 从左往右, 逐个字符进行匹配, 不会跳过任意的1个字符, 要求: 全部匹配才行.
        search: 查找的意思, 从左往右, 从任意的某个字符开始, 只要能匹配上即可.
        compile: 用于替换的.

    我们要学习的正则规则如下:
        .           代表: 任意的1个字符
        \.          取消.的特殊含义, 就是一个普通的. 校验邮箱的时候用, 例如: zhangsan@163.com
        a           代表: 就是1个普通的字符a
        [abc]       代表: a,b,c其中的任意1个字符
        [^abc]      代表: 除了a,b,c外, 任意的1个字符
        \d          代表: 所有的数字, 等价于 [0-9]
        \D          代表: 所有的非数字, 等价于 [^0-9]
        \s          代表: 空白字符, \n, 空格, \t等...
        \S          代表: 非空白字符, 即: 上述取反.
        \w          代表: 非特殊字符, 即: 字母, 数字, _ 下划线, 汉字
        \W          代表: 特殊字符, 即: 上述取反.

        ^
        $

        ?
        +
        *           数量词, 代表前边的内容, 至少出现 0次, 至多出现 n次
        {n}
        {n,}
        {n,m}

        |           或者的意思.
        ()
        \num

        扩展:
            (?P<分组名>)       给分组起名字
            (?P=分组名)        使用指定分组的内容
"""


# 导包
import re

# 需求: 获取字符串中 以数字开头的内容, 后续是啥无所谓.
# 演示: .           代表: 任意的1个字符(除了\n)
# result = re.match('it.', 'itA')
# result = re.match('it.', 'it\t')
# result = re.match('it.', 'it\n')    # 不匹配
# result = re.match('it.', 'i t1')    # 不匹配

# 演示: \.          取消.的特殊含义, 就是一个普通的. 校验邮箱的时候用, 例如: zhangsan@163.com
# 演示: a           代表: 就是1个普通的字符a
# result = re.match('.it\.', ' ait.')      # .it\.  任意1个字符 + it + .
# result = re.match('.it\.', ' aitb')      # 未匹配
# result = re.match('.it\.', ' ait.123')   # 未匹配

# 演示: [abc]       代表: a,b,c其中的任意1个字符
# result = re.match('[abc].*', 'asafs')
# result = re.match('[abc].*', 'bsafs')
# result = re.match('[abc].*', 'c123')
# result = re.match('[abc].*', 'd123')    # 未匹配

# 演示: [^abc]      代表: 除了a,b,c外, 任意的1个字符
# result = re.match('[^abc].*', 'asafs')  # 未匹配
# result = re.match('[^abc].*', 'bsafs')  # 未匹配
# result = re.match('[^abc].*', 'c123')   # 未匹配
# result = re.match('[^abc].*', 'd123')   # d123

# 演示: \d          代表: 所有的数字, 等价于 [0-9]
# result = re.match('\d.*', '1abc') # True
# result = re.match('\d.*', 'a1bc') # False

# 演示: \D          代表: 所有的非数字, 等价于 [^0-9]
# result = re.match('\D.*', '1abc')   # False
# result = re.match('\D.*', 'a1bc')   # True

# 演示: \s          代表: 空白字符, \n, 空格, \t等...
# result = re.match('it\s', 'it ')
# result = re.match('it\s', 'it\t')
# result = re.match('it\s', 'it\n')
# result = re.match('it\s', 'ita')

# 演示: \S          代表: 非空白字符, 即: 上述取反.
# result = re.match('it\S', 'it ')    # False, 未匹配
# result = re.match('it\S', 'it\t')   # False, 未匹配
# result = re.match('it\S', 'it\n')   # False, 未匹配
# result = re.match('it\S', 'ita')    # True

# 演示: \w          代表: 非特殊字符, 即: 字母, 数字, _ 下划线, 汉字
# result = re.match('it\w', 'it好')
# result = re.match('it\w', 'it_')
# result = re.match('it\w', 'it1')
# result = re.match('it\w', 'itxa')
# result = re.match('it\w', 'it+')    # 未匹配

# 演示: \W          代表: 特殊字符, 即: 上述取反.
result = re.match('it\W', 'it好')   # 未匹配
result = re.match('it\W', 'it_')    # 未匹配
result = re.match('it\W', 'it1')    # 未匹配
result = re.match('it\W', 'itxa')   # 未匹配
result = re.match('it\W', 'it+')


# 打印匹配结果
if result:
    info = result.group()       # 获取匹配到的内容
    print(f'匹配到: {info}')
else:
    print('未匹配!')

# 上述格式的: 简化版.
print(f'匹配到: {result.group()}' if result else '未匹配!')
```

10.正则-匹配多个字符

```python
"""
正则表达式介绍:
    概述:
        全称是 Regular Expression, 正则表达式, 即: 正确的, 符合特定规则的式子.
    作用:
        校验, 匹配数据的.
    细节:
        1. 学正则就是学正则表达式的 规则, 不要背, 因为这么多年了, 校验邮箱, 校验手机...等一些列的规则前辈们都写出来, 网上一搜一堆.
        2. 我讲正则的目的: 能用我们学的规则, 看懂别人写的 (正则表达式)式子, 且会根据需求修改即可.
        3. 正则不独属于任意的一门语言, Java, Python...都支持, 且: 正则规则都是一样的, 不同的是 写法不一样.

    Python中 正则的使用步骤:
        1. 导包
            import re
        2. 正则校验.
            re.match(pattern=正则表达式, str, flag)       参1: 正则表达式,  参2: 要校验的字符串, 参3:可选项, 例如: 忽略大小写, 多行模式等.
            re.search(pattern=正则表达式, str, flag)
            re.compile(正则表达式).sub(用来替换的内容, 要被替换的内容)
        3. 获取匹配结果.
            result = re.group()
    上述函数 介绍:
        match:  匹配的意思, 从左往右, 逐个字符进行匹配, 不会跳过任意的1个字符, 要求: 全部匹配才行.
        search: 查找的意思, 从左往右, 从任意的某个字符开始, 只要能匹配上即可.
        compile: 用于替换的.

    我们要学习的正则规则如下:
        .           代表: 任意的1个字符
        \.          取消.的特殊含义, 就是一个普通的. 校验邮箱的时候用, 例如: zhangsan@163.com
        a           代表: 就是1个普通的字符a
        [abc]       代表: a,b,c其中的任意1个字符
        [^abc]      代表: 除了a,b,c外, 任意的1个字符
        \d          代表: 所有的数字, 等价于 [0-9]
        \D          代表: 所有的非数字, 等价于 [^0-9]
        \s          代表: 空白字符, \n, 空格, \t等...
        \S          代表: 非空白字符, 即: 上述取反.
        \w          代表: 非特殊字符, 即: 字母, 数字, _ 下划线, 汉字
        \W          代表: 特殊字符, 即: 上述取反.

        ^
        $

        ?           数量词, 至少0次,至多1次
        +           数量词, 至少1次, 至多n次
        *           数量词, 代表前边的内容, 至少出现 0次, 至多出现 n次
        {n}         恰好n次, 多一次少一次都不行.
        {n,}        至少n次, 至多无所谓
        {n,m}       至少n次, 至多m次, 包括n和m

        |           或者的意思.
        ()
        \num

        扩展:
            (?P<分组名>)       给分组起名字
            (?P=分组名)        使用指定分组的内容
"""

import re

# 演示正则数量词, ?           数量词, 至少0次,至多1次
# result = re.match('it.?', 'ita')        # .?   任意的0个或者1个字符
# result = re.match('it.?', 'it\n')       # .?   任意的0个或者1个字符
# result = re.match('it.?', 'i t\n')      # 未匹配

# 演示正则数量词, +           数量词, 至少1次, 至多n次
result = re.match('it.+', 'it\n')       # 未匹配
result = re.match('it.+', 'it中')       # .+ 代表至少1个 至多任意个 任意的字符
result = re.match('it.+', 'it中, 真中, 非常中!')       # .+ 代表至少1个 至多任意个 任意的字符

result = re.match('it[abc]+', 'itaaabbc')   # [abc]+ 任意的1个或者多个 a,b,c组成的字符串
result = re.match('it[abc]+', 'itaaaa')   # [abc]+ 任意的1个或者多个 a,b,c组成的字符串
result = re.match('it[abc]+', 'it1aaaa')   # 未匹配


# 演示正则数量词, *           数量词, 代表前边的内容, 至少出现 0次, 至多出现 n次
result = re.match('it[abc]*', 'itaaabbc')   # [abc]+ 任意的1个或者多个 a,b,c组成的字符串
result = re.match('it[abc]*', 'itaaaa')   # [abc]+ 任意的1个或者多个 a,b,c组成的字符串
result = re.match('it[abc]*', 'i t1aaaa')   # 未匹配

# 演示正则数量词, {n}         恰好n次, 多一次少一次都不行.
# 前边恰好3个数字, 后续是啥无所谓.
result = re.match('[0-9][0-9][0-9].*', '623abc!@#')
result = re.match('[0-9]{3}.*', '623abc!@#')     # 效果同上
result = re.match('\d{3}.*', '623abc!@#')        # 效果同上
result = re.match('\d{3}.*', '6239abc!@#')        # 效果同上

# 演示正则数量词, {n,}        至少n次, 至多无所谓
# 前边至少2个整数, 后续是啥无所谓.
result = re.match('\d{2,}.*', '62123abc!@#')
result = re.match('\d{2,}.*', '6!@#')       # 未匹配

# 演示正则数量词, {n,m}       至少n次, 至多m次, 包括n和m
# 前边至少2个, 至多5个 整数或者字母或者下划线, 后续是啥无所谓.
result = re.match('[0-9a-zA-Z_]{2,5}.*', '62abc!@#')
result = re.match('[0-9a-zA-Z_]{2,5}.*', '__你12!@#')
result = re.match('[0-9a-zA-Z_]{2,5}.*', '6!2abc@#')     # 未匹配
result = re.match('[0-9a-zA-Z_]{2,5}.*', '_你12!@#')     # 未匹配


# 打印结果
print(f'匹配到: {result.group()}' if result else '未匹配!')
```

11.正则-校验开头和结尾

```python
"""
正则表达式介绍:
    概述:
        全称是 Regular Expression, 正则表达式, 即: 正确的, 符合特定规则的式子.
    作用:
        校验, 匹配数据的.
    细节:
        1. 学正则就是学正则表达式的 规则, 不要背, 因为这么多年了, 校验邮箱, 校验手机...等一些列的规则前辈们都写出来, 网上一搜一堆.
        2. 我讲正则的目的: 能用我们学的规则, 看懂别人写的 (正则表达式)式子, 且会根据需求修改即可.
        3. 正则不独属于任意的一门语言, Java, Python...都支持, 且: 正则规则都是一样的, 不同的是 写法不一样.

    Python中 正则的使用步骤:
        1. 导包
            import re
        2. 正则校验.
            re.match(pattern=正则表达式, str, flag)       参1: 正则表达式,  参2: 要校验的字符串, 参3:可选项, 例如: 忽略大小写, 多行模式等.
            re.search(pattern=正则表达式, str, flag)
            re.compile(正则表达式).sub(用来替换的内容, 要被替换的内容)
        3. 获取匹配结果.
            result = re.group()
    上述函数 介绍:
        match:  匹配的意思, 从左往右, 逐个字符进行匹配, 不会跳过任意的1个字符, 要求: 全部匹配才行.
        search: 查找的意思, 从左往右, 从任意的某个字符开始, 只要能匹配上即可.
        compile: 用于替换的.

    我们要学习的正则规则如下:
        .           代表: 任意的1个字符
        \.          取消.的特殊含义, 就是一个普通的. 校验邮箱的时候用, 例如: zhangsan@163.com
        a           代表: 就是1个普通的字符a
        [abc]       代表: a,b,c其中的任意1个字符
        [^abc]      代表: 除了a,b,c外, 任意的1个字符
        \d          代表: 所有的数字, 等价于 [0-9]
        \D          代表: 所有的非数字, 等价于 [^0-9]
        \s          代表: 空白字符, \n, 空格, \t等...
        \S          代表: 非空白字符, 即: 上述取反.
        \w          代表: 非特殊字符, 即: 字母, 数字, _ 下划线, 汉字
        \W          代表: 特殊字符, 即: 上述取反.

        ^           代表: 开头      '^[^abc].*'
        $           代表: 结尾

        ?           数量词, 至少0次,至多1次
        +           数量词, 至少1次, 至多n次
        *           数量词, 代表前边的内容, 至少出现 0次, 至多出现 n次
        {n}         恰好n次, 多一次少一次都不行.
        {n,}        至少n次, 至多无所谓
        {n,m}       至少n次, 至多m次, 包括n和m

        |           或者的意思.
        ()
        \num

        扩展:
            (?P<分组名>)       给分组起名字
            (?P=分组名)        使用指定分组的内容
"""

import re

# 演示  ^           代表: 开头
result = re.match('\d.*', '1abc')         # 必须以数字开头
result = re.search('\d.*', 'a1bc')       # 必须以数字开头
result = re.search('^\d.*', 'a1bc')       # 未匹配

# 演示  $           代表: 结尾
result = re.match('.*[a-zA-Z]', '123abc')
result = re.match('.*[a-zA-Z]', '123abc1')
result = re.match('.*[a-zA-Z]$', '123abc1')  # 未匹配

# 打印结果
print(f'匹配到: {result.group()}' if result else '未匹配!')
```

12.正则-或者

```python
"""
正则规则:
    |           或者的意思.
    ()
    \num

    扩展:
        (?P<分组名>)       给分组起名字
        (?P=分组名)        使用指定分组的内容
"""
import re

# 需求: 演示正则规则之 |

# 1. 定义列表, 记录水果.
fruit = ['apple', 'banana', 'orange', 'pear']

# 2. 遍历, 获取到每一种水果.
for value in fruit:
    # 3. 判断当前水果是否是喜欢吃的(苹果, 梨)水果, 并打印.
    result = re.match('apple|pear', value)
    # 4. 打印结果.
    if result:
        # print(f'喜欢吃: {value}')
        print(f'喜欢吃: {result.group()}')
    else:
        print(f'不喜欢吃: {value}')
```

13.正则-校验邮箱

```python
# 案例: 演示正则校验邮箱.

"""
正则规则:
    |           或者的意思.
    ()          代表分组.
    \num

    扩展:
        (?P<分组名>)       给分组起名字
        (?P=分组名)        使用指定分组的内容
"""
import re

# 需求: 匹配出163, 126, qq等邮箱, 格式为:  4 ~ 20位任意字母, 数字, _  + @标记符 + 域名163,126,qq + .com

# 校验邮箱, 格式为:  4 ~ 20位任意字母, 数字, _  + @标记符 + 域名163,126,qq + . + 后缀(任意2~3个字符)
result = re.match('[a-zA-Z0-9_]{4,20}@(163|126|qq)\.com', 'hello@163.com')

# 打印结果
if result:
    print(f'匹配到: {result.group()}')         # hello@163.com
    print(f'group(0), 即: 0组, 结果为: {result.group(0)}')   # 同上, hello@163.com
    print(f'group(0), 即: 0组, 结果为: {result.group(1)}')   # 同上, 163
else:
    print('未匹配到!')

```

14.正则-获取指定分组内容

```python
# 案例: 演示正则-获取指定分组内容.

"""
正则规则:
    |           或者的意思.
    ()          代表分组.
    \num

    扩展:
        (?P<分组名>)       给分组起名字
        (?P=分组名)        使用指定分组的内容
"""
import re

# 需求: 从 qq:qq号 这个格式的字符串中, 提取出qq 和 qq号

result = re.match('(qq):(\d{5,11})', 'qq:12306')


if result:
    print(f'匹配到: {result.group()}')       # qq:12306
    print(f'group(0), {result.group(0)}')   # qq:12306
    print(f'group(1), {result.group(1)}')   # qq
    print(f'group(2), {result.group(2)}')   # 12306
else:
    print('未匹配到!')

```

15.正则-校验html标签

```python
"""
案例: 演示正则校验 html标签.

正则规则:
    |           或者的意思.
    ()          代表分组.
    \num        \分组编号, 表示引入某组的内容.

    扩展:
        (?P<分组名>)       给分组起名字
        (?P=分组名)        使用指定分组的内容
"""
import re

# 需求1: 演示正则校验html标签, 单级标签.
# 方式1: 直接编写, 复制同样内容即可.
result = re.match('<[a-zA-Z]{1,4}>.*</[a-zA-Z]{1,4}>', '<html>hh</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值