【Python】python基础编程回顾(4)
PYTHON编程基础回顾
文件与模块
文件操作
在现实生活中对文件操作,一般遵循以下流程:
- 打开文件
- 读/写文件
- 保存文件
- 关闭文件
p.s. 在python中对文件的操作也是遵循以上步骤的
- 文件打开与关闭
【功能】
按照指定的打开模式,打开一个已经存在的文件,或者创建一个新文件【语法】
open('文件名称','打开模式')
【文件打开模式】
①一般而言,w表示写操作,r表示读操作,b表示追加操作;
②后缀b表示以二进制的格式对文件进行上述操作,+一般表示读写兼备;
③一般而言,读模式的指针落在文件开头;追加模式的指针落在文件结尾;写模式在打开文件不存在的情况下会对文件进行新建,在打开文件存在的情况下会对原文件进行覆盖。
④当使用二进制的形式打开文件并操作,就需要对新增的文字指定统一的编码格式【文件编码】
- 一般打开一个文件的默认编码是gbk(中文编码)
- 应该养成习惯在打开一个文件的时候即指定一个编码类型
open('文件路径','打开模式',encoding = '编码标准')
- 文件读写
①通过打开文件操作open,会返回一个文件对象;
②通过调用该文件对象内封装好的相关方法,即可实现对文件的读写操作;
③使用read只对文件进行部分读取时,文件指针会停留在上次读完的位置处,下一次读文件就会以该位置为起始;
④涉及到文件读写操作时,要格外注意文件的编码格式;如果将一个文件以二进制形式读取之后再转码输出,则需要编解码的规则一致才可。
①文件的写操作
'''
文件的写操作
'''
# 1. 使用open函数通过写模式打开一个已经存在的文件,或者创建一个新文件
fobj = open('test.txt','w')
fobj.write('这是打开后新增的内容')
fobj.close() #这里对文件关闭就会自动更新并保存# 2. 以二进制模式打开文件并操作
fobj = open('test.txt','wb') #这里指定二进制的模式,只是从字符串转换成了字节类型的数据
fobj.write('通过二进制模式打开文件并写入\n'.encode('gbk'))
fobj.close()# 3. 以追加的形式打开并操作文件
fobj = open('test.txt','a')
fobj.write('这是追加的一行文字')
fobj.close()
②文件的读操作
'''
文件的读操作
'''
# 1. 使用fileobj.read()读出文件内所有数据
fobj = open('test.txt','r')
print('---------读取文件内所有数据------------')
print(fobj.read())
fobj.close()#2. 使用fileobj.read(num)读出文件内指定数目的字符
fobj = open('test.txt','r')
print('-----------读取文件内指定个数(10)的字符---------')
print(fobj.read(10))
fobj.close()#3. 使用rb进行二进制读取,在不进行任何格式转换的情况下读到的就是一串二进制编码
fobj = open('test.txt','rb')
print('---------以二进制形式读取文件内的数据-------------')
data = fobj.read()
print(data)
print('---------如果对读取到的文件内容解码之后再输出--------')
print(data.decode('gbk'))
'''
运行结果:
---------读取文件内所有数据------------
通过二进制模式打开文件并写入
这是追加的一行文字
-----------读取文件内指定个数(10)的字符---------
通过二进制模式打开文
---------以二进制形式读取文件内的数据-------------
b'\xcd\xa8\xb9\xfd\xb6\xfe\xbd\xf8\xd6\xc6\xc4\xa3\xca\xbd\xb4\xf2\xbf\xaa\xce\xc4\xbc\xfe\xb2\xa2\xd0\xb4\xc8\xeb\n\xd5\xe2\xca\xc7\xd7\xb7\xbc\xd3\xb5\xc4\xd2\xbb\xd0\xd0\xce\xc4\xd7\xd6'
---------如果对读取到的文件内容解码之后再输出--------
通过二进制模式打开文件并写入
这是追加的一行文字
'''
③python上下文管理
在py程序中,诸如文件的打开、关闭,会话的建立与释放等牵扯到内存资源的成对操作,往往可以借助
with
的上下文管理模块进行自动处理。
【功能】
不管在处理文件过程中是否发生异常,都能保证with语句执行完毕后已经关闭打开的文件句柄。
【语法】
with open('文件名称','打开方式') as f:#执行的文件相关操作# 打开的文件对象统统用标识符f进行引用
- 案例——文件备份脚本
①满足基本逻辑:将旧文件的内容读出并写入到新文件之中
'''
应用:要求用户输入文件名称,编写一个可以自动完成文件备份的脚本
'''
def CopyFile():#接受用户输入的文件名filename = input('请输入要备份的文件名:')file_list = filename.split('.')#构造新的文件名并加上备份文字的后缀new_file = file_list[0]+'_备份.'+file_list[1]#通过打开旧文件,读取其中内容并重写进新文件之中即可oldfobj = open(filename,'r')newfobj = open(new_file,'w') #以写模式打开新文件,如果文件不存在则创建新文件data = oldfobj.read()newfobj.write(data) #将在旧文件中读取到的内容写入新文件之中oldfobj.close()newfobj.close()#调用该文件进行文件备份
CopyFile()
②深入优化:对于超大文件的备份,不再一次性将原文件的所有内容读出,而是以分块的形式分次读出,以防止内存占满
'''
应用:要求用户输入文件名称,编写一个可以自动完成文件备份的脚本
'''
def CopyFile():#接受用户输入的文件名filename = input('请输入要备份的文件名:')file_list = filename.split('.')#构造新的文件名并加上备份文字的后缀new_file = file_list[0]+'_备份.'+file_list[1]try:with open(filename,'r') as oldfobj,open(new_file,'a') as newfobj:#with上下文管理可以一次打开多个文件block = 1024 #设置每次读取1kB的数据while True:content = oldfobj.read(block)newfobj.write(content)if len(content)<block:break#except Exception as e:print(e)#调用该文件进行文件备份
CopyFile()
- 文件定位与部分操作
- (1)
fileobj.tell()
【概念】
文件定位,指的就是当前文件指针所读取到的光标位置。
【操作】
在读写文件的过程中,可以通过tell()
来获取当前光标位置。
【特点】
①读取文件fileobj.read(num)
是对原文件以当前光标位置为起始点,读取num个字符;
②fileobj.tell()
返回的指针位置是以字节为单位的。
- (2)
fileobj.truncate()
【概念】
在原有文件的基础上直接进行截取操作,只保留指定字符数目的数据。
【操作】
fileobj.truncate(num)
,对原文件fileobj对象只保留num个字符大小的数据。
【特点】
要注意在处理中文和不同编码时,截取的字符个数是有限制的(比如只能是偶数)
'''
文件指针随意定位
'''
with open('test.txt','w',encoding='gbk') as fobj:fobj.write('在苍茫的大海上\n')fobj.write('狂风卷积着乌云\n')with open('test.txt','r+',encoding='gbk') as fobj:#因为需要截取,所以还要赋予写权限fobj.truncate(6)print('对原文件截取6个字符,则此时文件全部内容为:')print(fobj.read())'''
运行结果:
对原文件截取6个字符,则此时文件全部内容为:
在苍茫
'''
- (3)
fileobj.seek()
【概念】
在操作文件的过程中,需要定位到其他位置进行操作
【操作】
fileobj.seek(offset,from),表示从给定的位置偏移一定的位置
offset
:是偏移量的单位字节,整数是往前偏移,负数就是往回偏移;from
:表示起始位置——0为文件开头,1为当前位置,2是文件末尾。【特点】
①如果要对文件对象使用seek方法,则需要以二进制的形式打开文件,否则其他形式打开的文件只允许从文件的开头计算光标的相对位置;
②以二进制形式读出文件,如果需要读出内容,则要按照编码规范进行解码fobj.read().decode('编码规范')
③如果文件内容是中文字符,则要注意一个中文字符和两个英文字符进行对应
'''
文件指针随意定位
'''
with open('test.txt','w',encoding='gbk') as fobj:fobj.write('在苍茫的大海上\n')fobj.write('狂风卷积着乌云\n')with open('test.txt','rb') as fobj:#因为需要截取,所以还要赋予写权限print('阅读原文件的4个字符:')print(fobj.read(4).decode('gbk'))print('利用seek将光标移动到文件开头,再读出内容:')fobj.seek(-4,1)print(fobj.read().decode('gbk'))'''
运行结果:
阅读原文件的4个字符:
在苍
利用seek将光标移动到文件开头,再读出内容:
在苍茫的大海上
狂风卷积着乌云
'''
模块操作
- 模块导入的方式
【模块相关概念】
①通俗来说,模块就是为了实现一些功能而封装好的一堆函数的py文件②在程序中如果要使用这个模块,通常需要先将模块导入
【模块搜索路径】
首先在文件的当前目录下搜索;
如果当前目录中不存在,则会去环境变量中搜索
如果以上路径中都找不到指定模块,则会搜索默认路径
p.s. 使用sys模块中的path变量,即print(sys.path)
即可以得到当前所有的环境变量路径
- 使用
import Modulename
直接导入整个模块
【导入流程】
使用import首次导入模块,程序内部会进行以下操作:
①打开模块文件
②执行模块对应的文件,将执行过程中产生的名字都丢到模块的名称空间中;
③在程序中会有一个模块的名称指向模块的名称空间【模块调用】
对于模块的调用,采用module_name.function_name
的形式,可以防止不同模块的同名方法导致引用错误
- 使用
from Modulename import function
导入一个模块中的指定函数
【导入流程】
使用import首次导入模块,程序内部会进行以下操作:
①以该模块为准创造一个模块的名称空间
②执行模块对应的文件,将执行过程中产生的名字都丢到模块的名称空间中;
③在当前执行文件的名称空间中拿到一个名字,该名字直接指向模块中的某一个名字【模块调用】
对于模块的调用,直接采用function_name
的形式,可以不加任何前缀地有指向性地调用模块中的函数
- 还可以使用as给导入的模块起别名,诸如
import Modulename as anotherame
- 应用os模块操作文件
【基本概念】
os模块中提供的都是对文件进行重命名、删除等一些操作
【操作命令】
【注意】
①在使用诸如os.remove()
或者os.rmdir()
等删除相关的方法时——
- 都需要先进行逻辑判断待删除的目标是否存在;
- 使用
os.rmdir()
方法只能删除空目录 ;- 若想对非空目录进行删除,则需要调用
shutil.rmtree()
方法,以文件树递归的形式进行删除操作。②在使用
os.mkdir()
等创建类型的指令时,也要注意——
- 可以通过指定绝对路径;来对文件夹进行创建;
- 如果指明路径下已经存在同名文件夹,则该步程序运行会报错;
- 如果想要通过设定绝对路径进行级联创建,则必须建立在前面的目录均存在的情况下;
- 如果想要实现多级创建,则需要使用
os.makedirs()
方法。③输出指定路径下的所有一级文件和文件夹名称:
- 如果使用
os.listdir()
,得到的是列表对象,可以用for循环将其中元素逐个输出;- 如果使用
os.scandir()
,得到的是迭代器对象,也要借助for循环得到其中每一个元素,且通常使用with
上下文管理模块,以达到自动释放资源的目的。
'''
os模块常用操作示例
'''
import os
import shutil#1. 修改文件名
os.rename('old_file_name','new_file_name')#2. 删除文件
os.remove('file_name')#3. 创建文件夹
os.mkdir('dir_name')
os.makedirs('dir1_name/dir2_name/.../dir_name')#------实现多级创建#4. 删除文件夹
os.rmdir('dir_name')
shutil.rmtree('dir1/dir2/.../file_name') #-----实现多级非空目录的删除#5. 获取当前文件的目录
os.getcwd()#6. 文件路径的相关操作
os.path.join('pat1h1','path2') #----直接返回将path2拼接在path1后形成的新路径
os.listdir('rootpath/')#---返回一个列表对象,其中包含指定目录下的所有文件和子目录名称
os.scandir('rootpath/') #----返回一个迭代器对象,其中也包含了指定目录下的所有文件和子目录名称
os.path.isfile('path') #---判断给定路径的对象是否为文件
os.path.isdir('path') #---判断给定路径的对象是否为目录# **输出给定根路径下所有的文件** 脚本
basePath = 'xxx'
for entry in os.listdir(basePath):if os.path.isfile(os.path.join(basePath,entry)):print(entry)
- 模块的制作、发布与安装
【模块】
在python中一个py类型的文件就可以作为一个模块【作用】
①模块可以使开发者有逻辑地去组织python代码
②模块是以库的形式对不同功能的代码进行封装,可以方便调用者使用;
③在模块中可以定义函数、类、变量等基本的数据;
④不同的模块中可以有相同的变量或函数名,但是每个模块内的变量或函数的作用域仅限于模块内部【分类】
内置模块/自定义模块/第三方模块
①模块的制作
通俗来说,在py文件内定义相关功能的函数即完成了模块的制作
使用模块的三种导入方式之一,就可以在另外一个py文件内对模块进行调用p.s.
①因为在导入模块时,会对模块的py文件进行执行,如果模块文件中还存在着测试代码或者主函数内有其他执行结果,则都会一并执行出来;
②对于上述问题,我们可以依赖魔术变量__name__来进行判断,从而得到不同的执行效果——即把模块文件中的测试等主函数运行代码都包含在if __name__ == '__main__':
中
'''
魔术变量:__name__
'''
#如果定义了一个py文件Module.py作为模块,在Module.py中有语句print(__name__)
#定义了另一个py文件main.py作为主文件来调用Module.py文件#在Module.py中执行结果为‘__main__’#在main.py中通过调用的形式,执行的结果为 ‘Module’
②模块的发布
平时我们所使用的第三方模块也是其他开发者发布出来的,需要安装后再进行调用。
- 首先需要将写好的包放到一个目录下
- 在前面放文件的目录下再创建一个setup.py文件,内部代码如下:
from distutils.core import setup
# name 模块名称
# version 版本号
# description 描述
# author 作者
# py_modules 要发布的内容,指定模块内要发布的函数或者是将需要发布的多个模块组织在一起
setup(name="my_module",version = "1.0",description="my module",zuthor="lilei",py_modules = ['test1.A','test1.B','test2.C','test2.D'])
- 进入到上面指定的路径下,键入并执行命令
python setup.py build
,完成模块的创建 - 继续在当前路径下,键入并执行命令
python setup.py sdist
,生成压缩包
使用pip工具的
pip install
命令可以直接借助python解释器对压缩文件进行解压并安装
- 使用
tree
命令即可以查看当前目录的结构,生成的模块同名的压缩包就第三方用于安装的文件
③模块的安装
- 将模块生成过程中得到的压缩文件进行解压,得到一个模块同名的文件夹
- 进入文件夹路径,执行
python setup.py install
命令进行安装 - 可以在python的安装目录下的site-packages下查看目录是否安装成功
④模块的调用
import Module_name
from Module_name import function_name
from Module_name import *
如果文件中存在
__all__
这个魔术变量,则使用最后一种方式导入模块中的方法时,只会导入__all__
中包含的函数;
格式:__all__ = ['func1','func2',...,'func_name']
垃圾回收
python中的内存回收
在python中使用的是引用计数机制为主,标记-清除和分代收集两种机制为辅的内存回收策略。
GC负责的主要任务如下:
①为新生成的对象分配内存;
②识别那些垃圾对象;
③从垃圾对象处回收内存
- 引用计数
- 原型与机制
'''
引用计数
'''
import sys#使用系统模块中的相关函数获得对象的引用计数
a = []
print('赋值了a=[]后的对象引用情况为:')
print(sys.getrefcount(a))b = a
print('执行完b=a后的对象引用情况为:')
print(sys.getrefcount(a))
'''
运行结果:
赋值了a=[]后的对象引用情况为:
2
执行完b=a后的对象引用情况为:
3
'''
①第一次输出引用计数情况为2,是因为sys.getrefcount()
函数中对a进行了调用,也算作一次引用;
②第二次输出引用计数情况为3,是因为一共有两个变量引用该对象,且第一次调用sys.getrefcount()
函数后又释放了该变量
③评价:[优点]简单且实时,将处理回收内存的时间分摊到了平时;
[缺点]维护引用计数会消耗资源;会存在循环引用的情况导致内存泄露。
- 循环引用与计数
#循环引用示例
list1 = []
list2 = []
list1.append(list2)
list2.append(list1)
'''
list1和list2之间相互引用,如果不存在其他对象对它们的引用,其二者的引用计数也仍然为1
它们所占用的内存将永远无法被回收
'''
- 标记清除
【概念介绍】
【提出背景】
因为python引用计数的原则不能处理循环数据结构——也即无法回收一组未使用的、互相指向,但任何一个都没有外部引用的对象。【实现机制】
import GC
gc.collect() #手动执行内存回收
- 分代收集
【概念介绍】
综上,也就是:在python中,把对象分为三代:一开始对象在被创建的时候,放在一代中;如果经过一次一代的垃圾检查后,该对象存活下来,则该对象就会被放到二代中;同理,如果经历了一次二代的垃圾检查后,该对象也存活下来了,则会被放入三代中。
- Python中的GC阈值
GC模块
- 引用计数
GC:Garbage Collection,垃圾回收
【导致引用计数+1的情况】
- 对象被创建
- 对象被引用
- 对象被作为参数,传递到下一个函数中
- 对象作为一个元素,存储在容器中
【导致引用计数-1的情况】
- 对象的别名被显式销毁
- 对象的别名被赋予新的对象
- 一个对象离开它的作用域,例如f函数执行完毕时,func函数中的局部变量
- 对象所在的容器被销毁,或从容器中删除该对象
- 垃圾回收
在python中默认开启自动垃圾回收:
- 可以通过
gc.disable()
关闭自动垃圾回收功能- 也可以通过手动调用
gc.collect()
,在关闭自动垃圾回收机制时,也能进行垃圾回收
触发垃圾回收的三种情况:
①当gc模块的计数器达到阈值的时候,自动回收垃圾;
②当调用gc.collect()
时,手动回收垃圾;
③程序退出的时候,python解释器来回收垃圾。
gc.get_count()
在gc模块中维护了一个长度为3的计数器列表,可以通过
gc.get_count()
来获取列表计数器形如
[num_1,num_2,num_3]
num_1
表示上一次一代垃圾检查之后,分配内存减去释放内存的数目;num_2
表示上一次二代垃圾检查之后,一代垃圾检查的次数;num_3
表示上一次三代垃圾检查之后,二代垃圾检查的次数。
gc.get_threshold()
gc中同样维护了一个自动垃圾回收的阈值,通过gc.threshold()函数能够获取一个长度为3的元组;每一次计数器的数值增加,gc模块就会检查计数器的值是否达到了阈值数目。如果是,则会执行对应代数的垃圾检查,然后重置计数器的值。
内存优化
- 小整数池与大整数池
【目的】
为了优化速度,使用整数对象池,避免为整数频繁申请和销毁内存空间【小整数池】
python中对小整数池的定义是[-5,256],这些整数对象是提前建立好的,不会被垃圾回收【大整数池】
python中的大整数池在初始化的时候是个空池子,需要自行创建;创建好了之后,就会把整数对象保存在池子里,下次使用相同数值的整数,就可以直接从池子里拿来使用,而无需再创建。
'''
内存优化
'''
#小整数池
a = 1
b = 1
print('对于两个整数a = 1和b = 1......')
print('a的内存地址为{},b的内存地址为{}'.format(id(a),id(b)))#大整数池
biga = 10000
bigb = 10000
print('对于两个整数biga = 10000和bigb = 10000......')
print('biga的内存地址为{},bigb的内存地址为{}'.format(id(biga),id(bigb)))'''
从结果上来看,大整数池和小整数池的执行效果是相同的
【运行结果】
对于两个整数a = 1和b = 1......
a的内存地址为140714343699264,b的内存地址为140714343699264
对于两个整数biga = 10000和bigb = 10000......
biga的内存地址为2131041310128,bigb的内存地址为2131041310128
'''
PEP8规范
python pep8原则主要是基于——
代码读取的次数比写入的次数多得多;旨在提供一种准则以提高代码的可读性并且使其在python代码中保持一致。主要内容包含:代码的规范,命名的规范,缩进的规范。
命令行参数
在使用python开发脚本,或者将python作为一个运维工具,或者其他工具需要接受用户参数运行时,就可以用到命令行传参。
- sys模块
- 通过
len(sys.argv)
获取参数列表的长度——参数的个数 - 通过
str(sys.argv)
获取参数列表的字符串信息
argv
返回的命令行参数是一个列表,第一个元素是py文件的文件名,可以通过切片操作只取得参数名,形如str(sys.argv[1:]))
p.s.
sys.argv
只能提供较为简单的命令参数获取方式,没有提供命令提示,无法做到像Linux命令一样
argparse
模块
该模块可以轻松编写用户友好的命令行界面。
√定义了程序需要的参数
√学会解析这些参数sys.argv
√自动生成帮助和用法信息,在用户给出程序无效参数时发出错误
- 添加参数选项
add_argument
name或flags代表有两种参数,其一是可选参数,其二是位置参数。
①使用诸如parser.add_argument('-f','--foo')
的形式来添加可选参数;
②使用诸如parser.add_argument('bar')
形式的参数来添加位置参数。
p.s.parser.args()
运行时,默认会用'-'
来认证可选参数,剩下的参数即为位置参数,在传参时必须给位置参数传值。√metaver:帮助信息中显示的参数名称
√const:保存一个常量
√default:默认值
√type:参数类型,默认为str
√choices:设置参数值的范围,如果该选项中的数据类型不是字符串,需要指定type
类型
√required:指定该参数是否为必选,默认为True
√dest:参数名称
- 课后练习
【需求说明】
实现命令行登录系统,如mysql登录
[mysql -u root -r 111111]
的效果
【功能实现】
import argparse#创建一个解析器对象
parser = argparse.ArgumentParser(prog="系统登录",usage="%(prog)s [options] usage",description = "my-description",epilog="my-epilog")#添加必选参数
parser.add_argument('loginType',type=str,help='登录系统的类型')#添加位置参数
parser.add_argument('-u',dest='user',type=str,help='用户名称')
parser.add_argument('-p',dest='pwd',type=str,help='密码')#进行参数解析
result = parser.parse_args()if(result.user == 'root' and result.pwd == '111111'):print('登录成功!')
else:print('登录失败!')'''
命令行输入出:
(base) D:\programming\Python\.idea>python 2048.py --help
usage: 系统登录 [options] usagemy-descriptionpositional arguments:loginType 登录系统的类型optional arguments:-h, --help show this help message and exit-u USER 用户名称-p PWD 密码my-epilog(base) D:\programming\Python\.idea>python 2048.py mysql -u root -p 111111
登录成功!'''
正则化
概述
- 正则表达式
【定义】
英文名称Regular Expression,又称为规则表达式。经常用于检索、替换那些符合某个模式(规则)的文本。【应用】
在主流操作系统和主流开发语言以及各类应用软件中,都可以看到正则表达式的应用。
- python正则表达式
python
在1.5版本后增加了re
模块(底层语言为C,匹配速度很快),其提供Perl
风格的正则表达式模块;
该模块使python
语言拥有全部的正则表达式功能。
complie()
函数根据一个模式字符串和可选的标志参数生成了一个正则表达式对象;该对象拥有一系列方法来进行正则表达式匹配和替换,re模块也提供了与这些方法功能完全一致的函数。
re模块与匹配规则
以下按照【正则表达式】的知识逻辑对re模块内的常用函数和方法进行讲解。
re.match()
方法
对于待匹配的字符串对象string
,按照给定的匹配模式或规则pattern
,按照既定的匹配方式flags
,进行规则匹配。
p.s.re.match()
方法只能匹配以什么字符串开头的模式
import re
str = 'Python is the bset language in the world'
res = re.match('P',str)#这样的匹配方式是精确匹配
print(res.group())#通过group()方法可取出匹配成功后的字符串
'''
输出:P
'''
re.match()
中的标志位(flags
)
①标志位及其含义:
re.l -------- 匹配对大小写不敏感
re.L--------本地化识别(locla-aware)的匹配
re.M--------多行匹配,影响^和$
re.S---------使匹配包括换行在内的所有字符
re.U--------根据Uniclde字符集解析所有字符,会影响到\w,\W,\b,\B
re.X---------通过给予更加灵活的格式使得正则表达式的书写更容易理解②用法与规范
- 如果同时使用多个标志位,用"
|
"进行分隔,比如re.l|re.M
MATCH.group()
对于正则匹配到的Match对象,我们可以通过使用group()方法来获取匹配到的表达式。
groups()
------ 返回一个包含所有小组字符串的元组(其中含有从1到所含的全部小组号)group(num)
------ 如果匹配到了多个组,那么传入相应的组号num,就会返回包含那些组所对应值的元组。
- 常用的匹配规则-匹配字符
符号 | 匹配规则 |
---|---|
.(点) | 匹配任意一个字符除了换行符\n |
[abc] | 匹配abc中的任意一个字符 |
\d | 匹配一个数字,即0-9 |
\D | 匹配非数字,即不是数字 |
\s | 匹配空白,即空格,tab键 |
\S | 匹配非空白,除空格、tab键之类的 |
\w | 匹配单词字符,即a-z,A-Z,0-9 |
\W | 匹配非单词字符 |
import re# 通过“.”的匹配查找指定姓的人名
data = '李一','王二','李三','李四','张五','周六'
pattern = '李.'for name in data:res = re.match(pattern,name)if res:print(res.group())
'''
运行结果:
李一
李三
李四
'''
#通过“[abc]”的匹配查找指定姓集合中的人名
data = '李一','王二','李三','李四','张五','周六'
pattern = '[李王]'for name in data:res = re.match(pattern,name)if res:print(res.group())
'''
运行结果:
李
王
李
李
'''
#可以使用简写方式定义一个更大范围的匹配集合 e.g.[a-z]
#\xx系列的匹配规则
#1.记住各个\x符号匹配的字符
#2. 可以使用多个转义符表示从开头匹配多个符合规则的字符,如\d\d\d\d表示从开头开始有4个数字
#3. 也可以使用\x*n的形式表示n个\x符号的匹配
import re
str1 = '123sedvg'
pattern1 = '\d'*2
res = re.match(pattern1,str1)
print(res.group())#通过group()方法可取出匹配成功后的字符串pattern2 = '\w\w\w\w'
ans = re.match(pattern2,str1)
print(ans.group())'''
运行结果:
12
123s
'''
#可以使用简写方式定义一个更大范围的匹配集合 e.g.[a-z]
- 常用的匹配规则-匹配次数
符号 | 匹配规则 |
---|---|
* | 匹配前一个字符出现0次或无数次 |
+ | 匹配前一个字符出现1次或无数次 |
? | 匹配前一个字符出现0次或1次 |
{m} | 匹配前一个字符出现m次 |
{m,} | 匹配前一个字符至少出现m次 |
{n,m} | 匹配前一个字符出现从n到m次 |
所谓的“无限次”,是指上述符号前面的匹配字符只要能够满足这里定义的匹配规则,就会一直匹配下去,无限次相当于最后返回的是一个最长的匹配结果。
#使用正则匹配规则定义python中变量的命名规范
pattern = '[a-zA-Z_]+[\w]'
#或者
pattern = '[a-zA-Z_][\w]'
- 常用的匹配规则-转移、开头和结尾
符号 | 匹配规则 |
---|---|
^ | 匹配字符串开头 |
$ | 匹配字符串结尾 |
\\ | 匹配’\'这个符号 |
- 编译函数
Re.compile()
【功能概述】
compile
函数将正则表达式的模式编译成一个正则表达式对象,这样可以保存所产生的正则表达式对象,使得重用效率更高。
本质上就是将一个字符串编译转换成了字节码【优势】
使用re
模块中的re.match(pattern,data)
函数时,每次调用都会将pattern
这个字符串转换成正则表达式对象;如果使用re.compile()
函数,则只需要转换一次
import re
#re.compile()
pattern = '\d{4}'
data = '1234567'reobj = re.compile(pattern)
res = reobj.match(data)
print('使用编译好的re对象调用匹配方法:')
print(res.group())#1234#reobj.match(data)也就等价于模块调用re.match(pattern,data)
print('直接使用re模块调用匹配方法:')
print(re.match(pattern,data).group())#1234
- 其他匹配方法
(1)re.search()
方法
【功能概述】
扫描待匹配的整个字符串,寻找第一个由该正则表达式模式产生匹配的位置,并返回相应的匹配对象实例MatchObject
【调用示例】
re.search(pattern,string,flags = 0)
【参数说明】
pattern
匹配的正则表达式string
要匹配的字符串flags
标志位,用于控制匹配方式,具体上同见re.match()
部分
(2)re.findall()
方法
【功能概述】
扫描待匹配的字符串,将所有的匹配结果组织成一个列表进行返回
【调用语法】
re.findall(string[,pos[,endpos]])
【参数说明】
string
待匹配的字符串pos
可选,指定字符串的起始位置,默认为0endpose
可选,指定字符串的结束位置,默认字符串长度
p.s.
re.search()
和re.findall()
都可以由compile
函数编译得到的matchobj
对象进行调用——matchobj.search()
和matchobj.findall()
分组匹配
- 匹配规则与字符
符号 | 匹配规则 |
---|---|
| | 匹配左右任意一个表达式 |
(ab) | 将括号中的字符作为一个分组 |
\num | 引用分组num匹配到的字符串 |
(?P) | 分组起别名 |
(?P=name) | 引用别名为name的分组匹配到的字符串 |
- 分组匹配示例
①’|'该符号表示一个或的关系,诸如a|b的匹配模式意味着只要匹配到了a就不会再对b进行匹配,有点类似逻辑运算符短路求值的意思;
②分组匹配用圆括号()来定义分组,按照组别进行匹配和输出匹配结果;
③使用\num的匹配形式是为了应对会重复出现的一些模式规则,比如说html的标签都是成对出现的;通过使用\num的形式可以避免重复书写
④起别名和引用别名为xx的分组匹配规则往往会成对出现,?P<name>
进行别名的命名,?P=name
表示引用该分组
# 分组匹配的圆括号
import re
#(ab)分组匹配,将括号中的字符作为一个分组
#比如座机号码 xxxx-xxxxxxxx分为区号和电话号码
pattern = '([0-9]*)-(\d*)'
res = re.match(pattern,'0745-888888888')
print('整个匹配结果:',res.group(0))#或者res.group()也直接输出整个匹配结果
print('匹配结果的第一个分组:',res.group(1))
print('匹配结果的第二个分组:',res.group(2))
'''
运行结果:
整个匹配结果: 0745-888888888
匹配结果的第一个分组: 0745
匹配结果的第二个分组: 888888888
'''
#(别名)分组引用
import re
#\num表示相同的匹配模式
msg = '<html><h1>test data</h1></html>'
pattern = r'<(.+)><(.+)>(.+)</\2></\1>'
res = re.match(pattern,msg)
#\2表示前面定义的分组匹配规则中的第二组
# 使用\num的形式对于多组匹配容易引起混乱print('匹配的第一组数据:',res.group(1))
print('匹配的第二组数据:',res.group(2))
print('匹配的第三组数据:',res.group(3))#因此就出现了给分组起别名的机制
data = '<div><h1>www.baidu.com</h1></div>'
pattern1 = r'<(\w*)><(\w*)>(.*)</\2></\1>' #不使用别名
pattern2 = r'<(?P<div>\w*)><(?P<h1>\w*)>.*</(?P=h1)></(?P=div)>'#使用别名res1 = re.match(pattern1,data)
res2 = re.match(pattern2,data)
print(res1)
print(res2)
贪婪模式与非贪婪模式
- 概念辨析
贪婪模式: 尝试匹配尽可能多的字符,在python中数量词默认是贪婪的;
非贪婪模式:尝试匹配尽可能少的字符模式转换:在匹配规则字符
‘*’
,‘?’
,‘+’
,‘{m,n}’
后面加上问号?
,就可以使得贪婪模式变成非贪婪模式
【Python】python基础编程回顾(4)相关推荐
- 数学建模python实现基础编程练习4
数学建模python实现基础编程练习4 1.使用networkx实现最短路和最短距离 import networkx as nx list1 = [(1,2,7),(1,3,3),(1,4,12),( ...
- python在线编程免费课程-Python少儿基础编程课程
Python基础编程 L5-L8 主要内容: 为了帮孩子打下坚实编程基础,妙小程设计Python基础课程,学习Python基础知识及相关数学.物理等知识,并将其运用在游戏作品制作中.并让孩子了解并掌握 ...
- 少儿编程python课程-Python少儿基础编程课程
Python基础编程 L5-L8 主要内容: 为了帮孩子打下坚实编程基础,妙小程设计Python基础课程,学习Python基础知识及相关数学.物理等知识,并将其运用在游戏作品制作中.并让孩子了解并掌握 ...
- python青少儿编程教程-Python少儿基础编程课程
Python基础编程 L5-L8 主要内容: 为了帮孩子打下坚实编程基础,妙小程设计Python基础课程,学习Python基础知识及相关数学.物理等知识,并将其运用在游戏作品制作中.并让孩子了解并掌握 ...
- 【Python】python基础编程回顾(3)
PYTHON编程基础回顾 面向对象基础-中 面向对象具有三大特性--继承.多态与封装: 在本部分将会讲到三大特性中的两个--继承与多态 析构方法 概述:当一个对象被删除或者被销毁时,python解释器 ...
- 数学建模python实现基础编程练习1
数学建模python实现编程练习1 习题来自<python数学实验与建模> 1.利用sympy库进行画单叶双曲面 用pyplot画的不是很理想,就用sympy画了,利用plot3D函数 f ...
- python在线编程免费课程-十大python零基础编程在线网课一对一费用多少钱
许多家长会认为少儿编程组织的人员不是专业计算机行业的毕业生,那么在训练孩子学习时如何教会孩子控制机器人呢?今天小编主要给大家分享小孩学编程难吗,希望对你们有帮助! 在国内,每个品牌都有一些非常专业的员 ...
- python入门编程题库-Python经典基础编程练习题(六)——每日10题
1.统计 1 到 100 之和 sum=0 for i in range(1,101): sum+=i print(sum) 2.求输入数字的平方,如果平方运算后小于 50 则退出 n= int(in ...
- python网课一般多少钱-排名前十的python零基础编程在线网课一对一费用多少钱
在这一波技术授权浪潮中,随着教育大数据技术的发展,个性化学习将逐渐成熟并成为教育的常态.接下来给大家讲讲人工智能教育的前景,感兴趣请往下看吧! 人工智能作为引领第四次工业革命的重要驱动力,不仅改变了人 ...
最新文章
- 关于共用体所占的内存空间的问题
- 记一次安装多版本php的四个雷区,你踩着了吗
- 错误: 程序包r2不存在_坚果 R2 使用体验:它是一款真旗舰,也是不一样的旗舰...
- 计算机进阶操作,新手进阶Win7系统操作使用手册
- 使用LXE_SP_CHECKSPELLING_MS进行ABAP文本拼写检查
- 【JS 逆向百例】某易支付密码 MD5+AES 加密分析
- Mysql的多表查询(表添加,多表查询练习:笛卡尔积、内连接、外连接、子查询、UNION组合查询)
- 知方可补不足~UPDLOCK更新锁的使用
- html网页框架案例代码,HTML网页框架代码
- 使用ESP8266/ESP8285做一个WIFI中继(WiFi信号放大器)
- [CS61b] Git设置、问题及解决方式
- php 判断客户端类型,基于php实现判断客户端类型
- 深度学习: 指数加权平均
- 华为 MATE7 调试 LOCAT 日志不输出问题
- matlab从无到有系列(八):M文件及函数的编写
- 一个bug看一天,写代码像cxk
- 关于手机-Android版本-基带版本,连续点击六次进入工厂模式。自定义版本点五次动态隐藏显示某应用。
- ebtables规则arpreply
- <机器学习>支持向量机(SVM)理论
- Django学习-app创建与注册