正则表达式
上周内容回顾
py文件的类型在模块导入的场景下分为两种类型执行文件 和被导入文件
内置的__name__可以区分这两个文件
如果所的文件是被导入文件那么__name__返回__文件名(模块名)
如果所在的文件是执行文件那么__name__返回__main__
常见的启动脚本
if __name__='__mian__':
文件实质是执行文件的时候才可以运行的代码
在pycharm中还提供了简便写法>>>:main+tab键
循环导入
文件之间的彼此导入彼此 循环导入
循环导入的缺陷 可能会造成程序的报错
避免循环导入的方式
能尽量做到所有的名字准备就绪之后 再导入使用 XX(不建议)
尽可能去避免循环导入
模块的查找顺序
1.优先去内存中查找是否已经存在模块的缓存数据
2.其次去内置中查找解释器是否提前准备了相应的数据 《注意!!py文件名不能与模块名冲突》
3.最后去以执行文件为准的sys.path中查找(类似于环境变量)
# 1.sys.path的确认始终参考执行文件即可
# 2.pycharm会自动将项目根目录添加到sys.path中
# 3.为了程序兼容性 项目根目录后续需要我们自己去操作
"""
如何理解兼容性
类似于写了一个游戏 是不是能够在多个系统平台下载并体验
绝对导入与相对导入、、
绝对导入
始终以项目根目录为基准导入模块即可
在使用绝对导入之需要考虑一件事情 就是根目录添加到sys.path
相对导入
相对导入只能在模块文件中使用 并且有很多限制(同目录、同级别...)
正常情况下相对导入可以节省一点代码的编写 但是很容易出问题
如果出问题了 还是比较推荐使用绝对导入
包、、
含有多个模块文件及__init__.py的文件夹
包的出现其实就是为了更好的去管理模块文件 (模块知识)
在使用包的两种情况
1.只导入了包名
这个时候相当于导入了里面的__init__.py
2.指名道姓的导入
跟到模块一致
软件开发目录规范、、、
文件夹的名字并不是固定的 可以变换(只不过我们前期学习先记住一个固定的模板)
ATM项目根目录
bin文件夹
启动文件的存放目录
eg:start.py
'''有时候启动文件是直接放在项目根目录 不需要文件夹'
conf文件夹
(配置文件的存放目录)
core文件夹
(项目整个运行逻辑的文件存放目录)
lib文件夹
(共同的功能存放目录 很多文件可能会用到)
log文件夹
(日志存放目录 日志就相当于是'监控' )
db文件夹
(核心数据存放目录)
readme文件
(类似系说明书 里面写多种不同的内容)
reaquirements.txt
(项目所需的 全部 模块名称及他们的对应版本)
* 软件开发目录规范
```python
# 文件夹的名字并不是固定的 可以变换(只不过我们前期学习先记住一个固定的模板)
ATM项目根目录
bin文件夹
启动文件的存放目录
eg:start.py
'''有时候启动文件是直接放在项目根目录 不需要文件夹'''
conf文件夹
配置文件的存放目录
eg:settings.py
core文件夹
项目整个运行逻辑的文件存放目录
eg:src.py
lib文件夹
共同的功能存放目录(很多文件都可能要用到的)
eg:common.py
log文件夹
日志存放目录(日志就相当于是'监控')
eg:log.txt
'''后期日志文件不会在程序中直接产生 而是借助于工具'''
db文件夹
核心数据存放目录
eg:userinfo.txt
'''文件可以作为数据库 但是最常见的还是各种主流数据库'''
readme文件
类似于项目说明书 里面可以写很多不同类型的内容
requirements.txt文件
项目所需的所有模块名称及对应的版本
'''我们后面所学的模块很多都有版本区别前期该文件可以忽略'''
ps:以后写稍微大一点的编程项目时 所有的名称最好都用英文
```
复制老师课堂笔记————元少亲笔···
今日内容概要···
今天我们所学到的是一个全新的知识 其实也不是太难也不是太简单 就是必须记住!!
京东注册页面获取手机号~~
有很多校验规则 手机号肯定是纯数字 必须十一位 并且必须是常规手机号开头 (事真多我选择不在京东购物)
根据我们以前所学肯定是难不倒各位 (难得住我、·) 不多比比直接上老师的代码
'''python实现手机校验功能'''
# 1.获取用户的手机号
phone_num = input('请输入您的手机号>>>:').strip()
# 2.先校验是否是11位
if len(phone_num) == 11:
# 3.再校验是否是纯数字
if phone_num.isdigit():
# 4.校验开头是否合法(随便写几个意思一下)
if phone_num.startswith('13') or phone_num.startswith('15') or phone_num.startswith(
'17') or phone_num.startswith('18'):
print('是一个正常的手机号')
else:
print('手机号开头不合法')
else:
print('手机号必须是纯数字')
else:
print('手机号必须是11位')
也是一个题目感兴趣可以做一下
我们今天的主角~~~
如何使用正则表达式来写出这个手机校验功能
import re
phone_number = input('please input your phone number : ').strip()
if re.match('^(13|14|15|18)[0-9]{9}$', phone_number):
print('是合法的手机号码')
else:
print('不是合法的手机号码')
相对于我们无脑写if else好了很多 不止一星半点
"""理解定义正是表达式:
正是表达式是一门独立的语言 专门用来匹配、校验、筛查所需数据、
任何编程语言都可以使用 在python 中如果想要用就必须借助于内置模块 #re!!
自己的话概括 什么是正则表达式
利用一些特殊符号(重点)组合取字符串中自己所需要的数据 (匹配、校验、筛选这几个字能算它的核心)
所以学习正则很大程度上就是在学习一些特殊符号的使用
xxxxxxxxxx 在匹配筛选查找数据的时候可以使用正则提供的符号也可以直接写目标数据
正则表达式之字符组在线测试网站:http://tool.chinaz.com/regex/
'''单个字符组默认一次只匹配一个字符'''
[0123456789] 匹配0到9之间的任意一个数字
[0-9] 匹配0到9之间的任意一个数字(简写)
[a-z] 匹配a到z之间的任意一个小写字母
[A-Z] 匹配A到Z之间的任意一个大写字母
[0-9a-zA-Z] 匹配任意一个数字或者大小写字母(没有顺序)
正则表达式之特殊字符串
'''前期就是死记硬背 使用频率高了之后自然就记住了'''
# 特殊符号默认也是一次匹配一个字符
. 匹配除换行符以外的任意字符
\w | 匹配数字、字母、下划线(后续筛选变量名可能用到)要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。 |
---|---|
\d | 匹配任意的数字 等价于 [0-9]. |
\t | 匹配一个制表符(tab键) |
^ | 匹配字符串的开始 |
eg:^9 | 找9并且这个9必须在开头 |
$ | 匹配字符串的结尾 |
eg:9$ | 找9并且这个9必须在末尾 |
\W 大写 | 匹配非字母或数字或下划线 |
\w | 匹配字母数字 |
\D | 匹配任意非数字 |
111 | 1111111111111111 |
---|---|
a|b | 匹配a或者b 管道符就是or(或)的意思 |
() | 给正则表达式分组 不影响正则匹配 |
[] | 字符组的概念(里面所有的数据都是或的关系) |
[^] | 上箭号出现在了中括号的里面意思是取反操作 |
正则表达式之量词
"""量词必须跟在表达式的后面 不能单独使用 目的是增加匹配的字符数"""
# 注意量词默认都是贪婪匹配(尽可能多的匹配):后面详细的讲解
* | 重复零次或者多次(默认就是多次:越多越好) |
---|---|
+ | 重复一次或者多次(默认就是多次:越多越好) |
? | 重复零次或者一次(默认就是一次:越多越好) |
重复n次 | |
重复最少n次最多多次(越多越好) | |
重复n到m次(越多越好) |
复杂的正则编写
# 校验用户身份证号码
身份证号码是一个长度为15或18个字符的字符串,如果是15位则全部由数字组成,首位不能为0;如果是18位,则前17位全部是数字,末位可能是数字或x
^[1-9][0-9]{14}
^[1-9][0-9]{16}[0-9x]
# 校验邮箱、快递单号、座机号...
"""很多常见的正则校验符号 不需要我们编写 直接百度查找即可"""
ps:百度的前提是自己能够看懂别人写的大致意思
^[1-9]\d{13,16}[0-9x]$
^[1-9]\d{14}(\d{2}[0-9x])?$
^([1-9]\d{16}[0-9x]|[1-9]\d{14})$
取消转义
\n \n False
\\n \n True
\\\\n \\n True
在python中还可以在字符串的前面加r取消转义 更加方便
1、反斜杠可以用来转义,使用r可以让反斜杠不发生转义。
2、字符串可以用+运算符连接在一起,用*运算符重复。
3、Python中的字符串有两种索引方式,从左往右以0开始,从右往左以-1开始。
4、Python中的字符串不能改变。
贪婪匹配非贪婪匹配
贪婪匹配是尽可能匹配多的字符,非贪婪匹配就是尽叮能匹配少的字符。
# 正则 # 待匹配的文本 # 结果
<.*> <script>alert(123)<script> 1条 贪婪匹配
以最后一个大括号的出现作为结束标志
<.*?> <script>alert(123)<script> 2条 非贪婪匹配
以第一个大括号的出现作为结束标志
量词默认都是贪婪匹配 如果想修改为非贪婪匹配 只需要在量词的后面加?即可
贪婪非贪婪通常都是利用左右两边的条件作为筛选依据
.* 贪婪匹配会匹配尽可能多的字符
非贪婪匹配的写法是.*?,多了一个?
re模块
在Python中需要通过正则表达式对字符串进⾏匹配的时候,可以使⽤⼀个python自带的模块,名字为re
在python中无法直接使用正则 需要借助于模块
1.内置的re模块
2.第三方的其他模块
import re
res = re.findall('a', 'jason oscar aaa') # findall(正则表达式,待匹配的文本)
print(res) # ['a', 'a', 'a', 'a', 'a'] # 结果是所有符合条件的数据 并且组织成了列表
res1 = re.search('a', 'jason oscar aaa') # search(正则表达式,待匹配的文本)
print(res1) # 查找到一个符合条件的数据就结束 没有则返回None
print(res1.group()) # a 没有则无法调用group() 直接报错
res2 = re.match('j', 'jason oscar aaa') # match(正则表达式,待匹配的文本)
print(res2) # None 从字符串的开头匹配 如果没有则直接返回None 类似于给正则自动加了^ 如果符合也只获取一个就结束
print(res2.group()) # j 没有则无法调用group() 直接报错
res3 = re.finditer('a', 'jason oscar aaa') # finditer(正则表达式,待匹配的文本)
print(res3) # 结果是一个迭代器对象 为了节省空间
print([obj.group() for obj in res3]) # ['a', 'a', 'a', 'a', 'a']
obj = re.compile('\d+') # 提前写好后续需要经常使用的正则
print(re.findall(obj,'asjd21hj13123j')) # 写一遍之后 直接反复调用即可
print(re.findall(obj,'234328748hgjghj')) # 写一遍之后 直接反复调用即可
print(re.findall(obj,'jhjhjh423432423')) # 写一遍之后 直接反复调用即可
每天一边奥迪封心
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下