九.python基础模块
1.模块
1.1 模块的概念
-
学习模块之前回顾下,我们为什么要学习函数呢? 之前我们写代码用的是基本的赋值以及条件及循环语句,来控制代码的逻辑,后来代码写的太多,可读性比较差 这个时候,我们用函数把特定的功能封装起来,使代码可读性变得更好,但是,函数都是在一个文件中存在的, 如果要写更大的程序,都放在一个文件中,这个时候可读性又变得很差,怎么办呢?
这个时候为了解决代码的可读性以及维护性,我们把一类的功能分别放到不同的文件中,这样每个文件中的代码 就相对较少,大大提高了代码的可维护性,以及可读性。(不仅仅是python这样,很多语言都采用这种方式) -
定义:在python中,一个.py 的文件就称之为一个模块。
-
使用模块的好处:
- 提高代码的可维护性
- 提高代码的可读性。
- 可以直接引用(比如我们用一个时间的模块,直接import time就可以了,不用自己写time的功能)
- 可以避免函数名冲突,相同名字的函数和变量可以在不同模块中存在,我们不需要考虑函数名冲突。(但是需要注意,内置函数也可能是一个模块,所以我们的模块名,尽量不要与内置函数名冲突)
-
模块的分类(在python中模块一共分为3类)
- python标准库
- 第三方模块
- 自定义模块
- 模块的导入方法
- import语句
- from...import... 语句
- from...import * 语句
注意:导入 * 是不好的,因为它常常产生难以阅读的代码,并且会容易产生名字冲突。(因为很多文件中可能有相同的函数,导致冲突)
1.2 模块库存放位置
1 C:\Users\Administrator>python 2 Python 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] 3 on win32 4 Type "help", "copyright", "credits" or "license" for more information. 5 >>> import sys 6 >>> for i in sys.path: 7 ... print(i) 8 ... 9 10 C:\python36\python36.zip 11 C:\python36\DLLs 12 C:\python36\lib #标准库 13 C:\python36 14 C:\python36\lib\site-packages #第三方模块 15 >>>
1.3 模块的导入方法
以上介绍模块导入的三种方法,这里用示例来演示模块的使用
示例文件如下文件名为test.py模块名为test:
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 4 print('from the test.py') 5 6 num = 10 7 8 def func1(): 9 print('test->func1->num',num) 10 11 def func2(): 12 print('test->func2') 13 func1() 14 15 def func3(): 16 global num 17 num=20
- import语句使用
1 #导入示例 2 >>> import test #第一次导入是加载到内存,再次导入相同模块会在内存中多一次引用计数 3 from the test.py #test模块中的顶级代码会在导入的时候就执行 4 >>> 5 6 #全局变量不冲突 7 8 >>> import test 9 from the test.py 10 >>> num = 20 11 >>> print(num) 12 20 13 >>> print(test.num) 14 10 15 >>> 16 17 #函数不冲突 18 19 >>> import test 20 from the test.py 21 >>> num = 20 22 >>> def func1(): 23 ... print('func1->num',num) 24 ... 25 >>> func1() 26 func1->num 20 27 >>> test.func1() 28 test->func1->num 10 29 >>> 30 31 #全局变量不冲突 32 33 >>> import test 34 from the test.py 35 >>> num = 20 36 >>> test.func3() 37 >>> print(num) 38 20 39 >>>
当有相同种类的模块,导入的时候我们可以起别名
1 #例如test模块有以下两个函数 2 def func1(): 3 print("func1") 4 5 def func2(): 6 print("func2") 7 8 #别名导入方法 9 10 import func1 as test1 11 import func2 as test2 12 13 #好处是模块较多的时候我们可以自定义别名进行区分
- from...import... 语句使用
import导入是导入整个模块,在使用的时候我们必须用(模块名.函数名来获取),当我们要获取单一方法的时候可以用from...import...的方式
1 #结合以上示例 2 3 >>> from test import func1 4 >>> func1() #这里可以直接调用而非test.func1()来调用 5 test->func1->num 20 6 >>> 7 8 #导入func1函数,执行的时候会回到test中寻找变量 9 10 >>> from test import func1 11 from the test.py 12 >>> func1() 13 test->func1->num 10 14 >>> 15 16 #导入func2函数,执行时候调用func1也会回到test中的func1寻找 17 18 >>> from test import func2 19 from the test.py 20 >>> func2() 21 spam->func2 22 test->func1->num 10 23 >>> 24 25 #导入func1函数,在本作用域又创建同名函数,这时候会覆盖 26 27 >>> from test import func1 28 >>> func1() 29 test->func1->num 20 30 >>> 31 >>> 32 >>> def func1(): 33 ... print("func1") 34 ... 35 >>> func1() 36 func1 37 >>>
- from...import * 语句使用
这种方法不建议使用,因为模块中会有相同的函数,这样后导入的就会覆盖先导入的,导致问题的出现。
from...import * 不会导入以_开头的变量或函数。
可以用__all__来控制*号
比如:__all__['func1','func2'] ,这样使用from test import *的时候,只会导入func1和func2这两个方法。
1.4 模块的搜索路径
模块加载的先后顺序
- 内存中加载的模块
python解释器在启动时会自动加载一些模块,可以使用sys.modules查看 - 内置模块
比如sys模块,在python的环境变量下找不到 - sys.path路径中的模块(sys.pathsys.path路径位置寻找顺序:1.执行文件所在的当前目录,PTYHONPATH(环境变量))
1 >>> import sys 2 >>> sys.path 3 ['', 'C:\\Python3\\python35.zip', 'C:\\Python3\\DLLs', 'C:\\Python3\\lib', 'C:\\Python3', 'C:\\Python3\\lib\\site-packages'] 4 >>>
1.5 if __name__ == '__main__':语句
- if __name__ == '__main__':语句是在python脚本(模块)最后执行的,可以通过模块的全局变量__name__来查看模块名。
- 作用:在执行脚本的时候会执行此语句,因为在执行脚本的时候全局变量__name__=='__main__',但是在被当作模块导入的时候,__name__=='导入的模块名',一般用于脚本内测试会执行,当作模块导入的时候不会执行。
例如源文件如下,文件名test.py:
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 4 def run(): 5 print('123') 6 print(__name__) 7 8 if __name__ == '__main__': 9 run()
当作脚本运行时的结果:
C:\Users\Administrator>python test.py 123 __main__
当作模块导入的运行结果:
C:\Users\Administrator>python Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:18:55) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import test >>> test.run() 123 test >>>
2.包
2.1 包的概念
- python程序由包(package)、模块(module)和函数组成。模块是一系列函数组成,而包则是一系列模块的组合。
- 特点:
1.包含一个__init__.py的文件夹,导入包其实就是导入__init__.py文件。
2.包只是模块的一种封装模式,也可以理解为模块。只是把模块用文件夹封装。
3.不同包下的同名模块在导入的时候也不会冲突。
2.2 导入包的示例
2.2.2 from ... import ...
- from ... import ... 导入文件时,比如from a.b.c import d ,这里abc都是包名,而d则是最后一个包里的函数,切记。
2.2.3 from ... import *
- from ... import * 导入所有文件时,比如from a.b.c import * 则会导入c这个包里的所有内容,包也能限制导入哪一个,可以回忆下定制模块导入的内置方法,__all__,在包里可以在__init__.py中定义__all__=['方法1','方法2',‘方法3’],当使用from a.b.c import * 会导入c中的'方法1','方法2',‘方法3’。
2.2.4 __init__.py文件
- 不管是哪种方式,只要是第一次导入包或者是包的任何其他部分,都会首先执行包下的__init__.py文件,这个文件可以为空,但是也可以存放一些初始化包的代码。
2.2.5 绝对导入和相对导入
- 绝对导入和相对导入类似于linux下的绝对路径和相对路径,比如我的绝对导入路径是,from a.b.c import d ,这时候我在b的包中想导入包的内容,就可以用from ..a import 'a下的内容'。
2.2.6 import
- 单独导入包名称时不会导入包中所有包含的所有子模块,如我的包目录为/a/b/c ,这时候我运行import a,但是我执行a.b.c.d()的时候,会报AttributeError异常,这个时候的解决办法是:在a包目录下的__init__.py文件中写入from . import b,并且在b的目录下的__init__.py文件中写入from . import c。
3.常用模块介绍
3.1 os模块
1 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 2 os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd 3 os.curdir 返回当前目录: ('.'),相当于shell的cd . 4 os.pardir 获取当前目录的父目录字符串名:('..'),可以结合os.chdir(os.pardir)返回上层目录。相当于shell的cd .. 5 os.makedirs('dirname1/dirname2') 可生成多层递归目录,相当于shell中mkdir -p 6 os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推 7 os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname 8 os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname 9 os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印 10 os.remove() 删除一个文件 11 os.rename("oldname","newname") 重命名文件/目录 12 os.stat('path/filename') 获取文件/目录信息 13 os.sep 输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/" 14 os.linesep 输出当前平台使用的行终止符,win下为"\r\n",Linux下为"\n" 15 os.pathsep 输出用于分割文件路径的字符串 win下为 ';',Linux下为 ':' 16 os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix' 17 os.system("bash command") 运行shell命令,直接显示 18 os.environ 获取系统环境变量 19 os.path.abspath(path) 返回path规范化的绝对路径 20 os.path.split(path) 将path分割成目录和文件名二元组返回 21 os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素 22 os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素 23 os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False 24 os.path.isabs(path) 如果path是绝对路径,返回True 25 os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False 26 os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False 27 os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略 28 os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间 29 os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间 30 os.path.getsize(path) 返回path的大小
3.2 sys模块
1 sys.argv 命令行参数List,第一个元素是程序本身路径,例如执行python test.py 1 2 3,len(sys.argv)==4,sys.argv[0]是test.py,sys.argv[1]是1 ... 2 sys.exit(n) 退出程序,正常退出时exit(0) 3 sys.version 获取Python解释程序的版本信息 4 sys.maxint 最大的Int值 5 sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值sys.platform 返回操作系统平台名称 6 sys.getdefaultencoding() 获取系统当前编码,一般默认为'utf-8'。 7 sys.stdin 标准输入 8 sys.stdout 标准输出 9 sys.stderr 错误输出 10 sys.stdout.flush() 如果一个程序是1s输出一次,默认系统会每隔一段时间一起输入,这句的意思是实时输出。
3.3 random模块
1 import random 2 3 print(random.random()) #用于生成一个0到1的随机符点数: 0 <= n < 1.0 4 print(random.randint(1,2)) #用于生成一个指定范围内的整数 5 print(random.randrange(1,10)) #从指定范围内,按指定基数递增的集合中获取一个随机数 6 print(random.uniform(1,10)) #用于生成一个指定范围内的随机符点数 7 print(random.choice('zhagnsan')) #从序列中获取一个随机元素 8 li = ['zhangsan','lisi','wangwu'] 9 random.shuffle(li) #用于将一个列表中的元素打乱 10 print(li) 11 li_new = random.sample(li,2) #从指定序列中随机获取指定长度的片断(从li中随机获取2个元素,作为一个片断返回) 12 print(li_new)
1 #随机取五位验证码,大小写字母加数字,字母和数字出现的概率相等 2 3 def vcode(): 4 ret = "" 5 for i in range(5): 6 num = random.randint(0,9) #随机从(0-9)取一个数字 7 zimu = chr(random.randint(65,122)) #随机从大小写字母取一个字母 8 result = str(random.choice([num,zimu])) #字母和数字出现的概率相等 9 ret += result 10 return ret 11 print(vcode())
3.4 time模块
- 在python中表现时间的方式有三种:
1.时间戳
2.结构化时间
3.字符串时间
对于计算机来说只认识时间戳,对于我们来说,能看懂的是结构化时间和字符串时间。time模块其实就是这三种方式之间的转换而已。
图形化3种类转换示例:

转换示例:
1 >>> import time 2 #时间戳格式(时间戳表示的是从1970年1月1日00:00:00开始按秒计算到现在) 3 >>> print(time.time()) 4 1502637958.9958205 5 >>> 6 7 #结构化时间格式(本地时间) 8 >>> print(time.localtime()) 9 time.struct_time(tm_year=2017, tm_mon=8, tm_mday=13, tm_hour=23, tm_min=24, tm_sec=55, tm_wday=6, tm_yday=225, tm_isdst=0) 10 #结构化时间(格林威治时间,标准时间) 11 >>> print(time.gmtime()) 12 time.struct_time(tm_year=2017, tm_mon=8, tm_mday=13, tm_hour=15, tm_min=25, tm_sec=7, tm_wday=6, tm_yday=225, tm_isdst=0) 13 >>> 14 15 16 ###开始转换### 17 #将结构化时间转换成时间戳 18 >>> print(time.mktime(time.localtime())) 19 1502638217.0 20 >>> 21 #将结构化时间转换成字符串时间 22 >>> print(time.strftime("%Y-%m-%d %X",time.localtime())) #X代表%H-%M-%S 23 2017-08-13 23:35:20 24 >>> 25 #将字符串时间转换为结构化时间 26 >>> print(time.strptime("2017-08-13 23:35:20","%Y-%m-%d %X")) 27 time.struct_time(tm_year=2017, tm_mon=8, tm_mday=13, tm_hour=23, tm_min=35, tm_sec=20, tm_wday=6, tm_yday=225, tm_isdst=-1) 28 >>>
固定字符串转换("Sun Aug 13 23:39:08 2017" 转换成这样的格式):
图形化示例:

转换示例:
1 #结构化时间转换成固定的字符串表达时间 2 import time 3 >>> print(time.asctime()) #asctime参数为空,默认参数为time.localtime(),所以转化的是结构化时间 4 Sun Aug 13 23:47:23 2017 5 >>> 6 7 #时间戳转换成固定的字符串表达时间 8 >>> print(time.ctime()) #ctime参数为空,默认参数为time.time(),所以转化的是时间戳 9 Sun Aug 13 23:50:11 2017 10 >>>
3.5 json&pickle模块
序列化:
- json,用于字符串 和 python数据类型间进行转换
- pickle,用于python特有的类型 和 python的数据类型间进行转换
方法:
- Json模块提供了四个功能:dumps、dump、loads、load
- pickle模块提供了四个功能:dumps、dump、loads、load
方法的特性:
- dumps可以把特定的对象序列化处理为字符串
- loads可以把序列化的字符串进行反序列化成相应的类型
- dump和load其实和dumps和loads是一样的原理,唯一不同的以下用示例介绍。
区别:
1.json可以在任何支持json格式的地方转换,而pickle只能用于python当中。
2.在json里dump文件是以字符串形式存储的,而pickle是以字节的方式存储的。
json的使用方法:
1. 把字典转换成json形式的字符串写入文件中 (用两种方法演示dumps和dump)
方法一(dumps):
1 import json 2 dic = {'name': 'zhangsan'} 3 dic = json.dumps(dic) #将dic转换成json格式 4 f = open("hello", "w") 5 f.write(dic) #将json格式内容写入文件
方法二(dump)
1 import json 2 dic = {'name': 'zhangsan'} 3 f = open("hello", "w") 4 dic = json.dump(dic, f) #将文件对象和dic对象直接格式化并写入文件
结果:
1 {"name": "zhangsan"}
总结:dump和dumps的区别在于dump是将字典直接序列号并写入文件,而dumps是先生成json对象,然后再写入文件,推荐使用后者。
2.把文件中json类型的字符串读取出来转换成字典(用两种方法演示loads和load)
方法一(loads):
1 import json 2 f = open('hello','r') 3 f = json.loads(f.read()) #读取文件对象,然后进行loads格式化。 4 print(f) 5 print(type(f))
方法二(load):
1 import json 2 f = open('hello','r') 3 f = json.load(f) #直接将文件进行load操作 4 print(f) 5 print(type(f))
结果:
1 {'name': 'zhangsan'} 2 <class 'dict'>
总结:load和loads的区别在于load是直接将文件进行load操作,而loads是将文件读取的内容进行loads操作,推荐使用后者。
json的dumps,loads,dump,load功能总结:
- json.dumps(x) 把python的(x)原对象转换成json字符串的对象,主要用来写入文件。
- json.loads(f) 把json字符串(f)对象转换成python原对象,主要用来读取文件和json字符串
- json.dump(x,f) 把python的(x)原对象,f是文件对象,写入到f文件里面,主要用来写入文件的
- json.load(file) 把json字符串的文件对象,转换成python的原对象,只是读文件
pickle和json的使用方法相同,使用可以参考json示例。
3.6 hashlib模块
- hashlib 模块提供了很对加密算法,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法。
特点:
- 内容相同则hash运算结果相同,内容稍微改变则hash值则变
- 不可逆推
- 相同算法:无论校验多长的数据,得到的哈希值长度固定。
- 明文变成密文,不能反解
用途:
- 一般数据库密码是hash值
- 文件在网络上传输验证文件是否被篡改用hash值
以下只用md5方式加密来介绍(其他方式只是换个加密算法就可以):
1 import hashlib 2 m = hashlib.md5() #这里可以使用以上的任意算法,算法越复杂,验证时间越长 3 m.update('hello'.encode('utf8')) #将字符串hello转换成md5加密后串 4 print(m.hexdigest()) #打印md5加密串,值为5d41402abc4b2a76b9719d911017c592 5 6 7 #注意:把一段很长的数据update多次,与一次update这段长数据,得到的结果一样 8 ######################################################################################## 9 import hashlib 10 m = hashlib.md5() 11 m.update('hello'.encode('utf8')) 12 print(m.hexdigest()) #hello字符串,md5值为5d41402abc4b2a76b9719d911017c592 13 m.update('world'.encode('utf8')) 14 print(m.hexdigest()) #字符串,md5值为fc5e038d38a57032085441e7fe7010b0 15 16 ######################################################################################## 17 n = hashlib.md5() 18 n.update('helloworld'.encode('utf8')) 19 print(n.hexdigest()) #字符串helloworld,md5值为fc5e038d38a57032085441e7fe7010b0,可见持续的update等于拼接字符串之后的md5 20 ########################################################################################
以上的加密算法存在缺陷,相同的字符串的hash值永远不变,这就意味着可以生成一大堆密码的hash来反解,这种方法叫做撞库。
示例如下:
1 import hashlib 2 3 obj = hashlib.md5() 4 obj.update("admin".encode("utf8")) 5 print(obj.hexdigest()) #21232f297a57a5a743894a0e4a801fc3 6 #以上假如我知道了admin的md5是21232f297a57a5a743894a0e4a801fc3,那么以后我看到这个md5就知道是admin,这叫撞库反解。 7 8 #解决办法 9 import hashlib 10 11 obj = hashlib.md5("aaabbbccc".encode("utf8")) #这种方式叫加盐,给别人加上破解的难度 12 obj.update("admin".encode("utf8")) 13 print(obj.hexdigest()) #9887ad575ac3affc801e3ede4c447c5d 14 #总结:加盐之后得出的md5其实就是"aaabbbcccadmin"的md5字符串。
如果还是觉得不安全的话,可以用一个更安全的模块来解决,这个模块叫hmac。
hmac模块示例:
1 import hmac 2 3 #例一(两次追加的md5) 4 h1=hmac.new('aabbcc') 5 h1.update('hello') 6 h1.update('world') 7 print(h1.hexdigest()) 8 d9b9beb880d9451d1f90526897640f6e 9 #例二(两次追加合并的md5) 10 h2=hmac.new('aabbcc') 11 h2.update('helloworld') 12 print(h2.hexdigest()) 13 d9b9beb880d9451d1f90526897640f6e 14 #例三(合并hmac.new,可见hmac.new并不是拼接就能得到,它内部对我们创建key和内容再进行了加密处理。) 15 h3=hmac.new('aabbcchelloworld') 16 print(h3.hexdigest()) 17 d77fd6f3df4f2420845c0d5431b488bc
3.7 shutil模块
- 高级的 文件、文件夹、压缩包 处理模块
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # @Author : All is well 4 # @File : shutil示例.py 5 # @Software: PyCharm 6 7 import shutil 8 #将文件内容拷贝到另一个文件中 9 shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w')) 10 11 #拷贝文件,目标文件无需存在 12 shutil.copyfile('old.xml', '1.log') 13 14 #仅拷贝权限。内容、组、用户均不变 15 shutil.copymode('old.xml', '1.log') 16 17 #仅拷贝状态的信息,包括:mode bits, atime, mtime, flags,目标文件必须存在 18 shutil.copystat('f1.log', 'f2.log') 19 20 #拷贝文件和权限 21 shutil.copy('a.log', 'b.log') 22 23 #拷贝文件和状态信息 24 shutil.copy2('a.log', 'b.log') 25 26 #递归的去拷贝文件夹,目标目录不能存在,222的父目录必须有w权限,ignore的意思是排除 27 shutil.copytree('111','222',ignore=shutil.ignore_patterns('a.txt','tmp*')) 28 29 #通常的拷贝都把软连接拷贝成硬链接,即对待软连接来说,创建新的文件 30 shutil.copytree('f1', 'f2', symlinks=True, ignore=shutil.ignore_patterns('*.txt', 'tmp*')) 31 32 #递归的去删除文件 33 shutil.rmtree('tmp') 34 35 #递归的去移动文件,它类似mv命令,其实就是重命名。 36 shutil.move('111', '222') 37 38 # 将 /data 下的文件打包放置当前程序目录 39 ret = shutil.make_archive("data_bak", 'gztar', root_dir='/data') 40 41 # 将 /data下的文件打包放置 /tmp/目录 42 ret = shutil.make_archive("/tmp/data_bak", 'gztar', root_dir='/data') 43 44 #============================================================= 45 import zipfile 46 47 # 压缩 48 z = zipfile.ZipFile('aaa.zip', 'w') 49 z.write('a.log') #指定打包文件a.log 50 z.write('data') #指定打包文件data目录 51 z.close() 52 53 # 解压 54 z = zipfile.ZipFile('aaa.zip', 'r') 55 z.extractall(path='.') #解压到当前目录 56 z.close() 57 #============================================================= 58 59 import tarfile 60 61 # 压缩 62 t=tarfile.open('aaa.tar','w') 63 t.add('a.log',arcname='a.bak') #arcname指定打包内的名字 64 t.add('/test1/',arcname='test.dir') 65 t.close() 66 67 68 # 解压 69 t=tarfile.open('aaa.tar','r') 70 t.extractall('/tmp') #解压到tmp目录 71 t.close() 72 73 #=============================================================
3.8 logging模块
3.9 configparse模块
3.10 re模块
就其本质而言,正则表达式(或 RE)是一种小型的、高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。
字符匹配(普通字符,元字符):
普通字符:大多数字符和字母都会和自身匹配,如 print(re.findall('abc', 'abcdefg'))结果:['abc']
元字符:. ^ $ * + ? { } [ ] | ( ) \
元字符之. ^ $ * + ? { }
1 import re 2 3 ret = re.findall('a..d','abcdefg') #.匹配单个字符 4 print(ret) #['abcd'] 5 6 ret=re.findall('^a...e','abcdefgabcdefg') #^匹配字符以谁开头 7 print(ret) #['abcde'] 8 9 ret=re.findall('a...e$','abcdefgabcdefgabcde') #^匹配字符以谁结尾 10 print(ret) #['abcde'] 11 12 ret=re.findall('abc*','abcccc') #贪婪匹配[0,+oo] 13 print(ret) #['abcccc'] 14 15 ret=re.findall('abc+','abccc') #[1,+oo] 16 print(ret)#['abccc'] 17 18 ret=re.findall('abc?','abccc') #[0,1] 19 print(ret)#['abc'] 20 21 ret=re.findall('abc{1,4}','abcabccabcccabccccabccccc') #匹配前一个字符m次,或者m到n次 22 print(ret)#['abc', 'abcc', 'abccc', 'abcccc', 'abcccc'] 贪婪匹配 23 24 # 注意:前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配 25 ret=re.findall('abc*?','abcccccc') #惰性匹配 26 print(ret) #['ab']
元字符之字符集[]
1 import re 2 3 ret=re.findall('a[bc]d','abdacd') 4 print(ret) #['abd', 'acd'] 5 6 ret=re.findall('[.*+?${1,3}]','a.cd+') 7 print(ret) #['.', '+'] 8 9 #注意:在字符集里有功能的符号: - ^ \ 10 11 ret=re.findall('[1-9]','1a2bc3def') #1-9任意数字都匹配。 12 print(ret) #['1', '2', '3'] 13 14 ret=re.findall('[a-z]','abcd') 15 print(ret) #['a', 'b', 'c', 'd'] a-z任意一个都匹配。 16 17 ret=re.findall('[^ab]','asdfbasdf') #非a或者非b的字符。 18 print(ret) #['s', 'd', 'f', 's', 'd', 'f'] 19 20 ret=re.findall('[^0-9]','1a2b3c4d') #非数字的字符。 21 print(ret) #['a', 'b', 'c', 'd']
元字符之转义符\
1 # 反斜杠后边跟元字符去除特殊功能,比如\. 2 # 反斜杠后边跟普通字符实现特殊功能,比如\d 3 # 4 # \d 匹配任何十进制数;它相当于类 [0-9]。 5 # \D 匹配任何非数字字符;它相当于类 [^0-9]。 6 # \s 匹配任何空白字符;它相当于类 [ \t\n\r\f\v]。 7 # \S 匹配任何非空白字符;它相当于类 [^ \t\n\r\f\v]。 8 # \w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。 9 # \W 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_] 10 # \b 匹配一个特殊字符边界,比如空格 ,&,#等 11 import re 12 ret=re.findall('\d','1a2b3c4d') #匹配任何十进制数 13 print(ret) #['1', '2', '3', '4'] 14 15 ret=re.findall('\D','1a2b3c4d') #匹配任何非数字字符 16 print(ret) #['a', 'b', 'c', 'd'] 17 18 ret=re.findall('\s','I am \tall \nis \rwell') #匹配任何空白字符 19 print(ret) #[' ', ' ', '\t', ' ', '\n', ' ', '\r'] 20 21 ret=re.findall('\S','I am \tall \nis \rwell') #匹配任何非空白字符 22 print(ret) #['I', 'a', 'm', 'a', 'l', 'l', 'i', 's', 'w', 'e', 'l', 'l'] 23 24 ret=re.findall('\w','123abc.?${}*+') #匹配任何字母数字字符 25 print(ret) #['1', '2', '3', 'a', 'b', 'c'] 26 27 ret=re.findall('\W','123abc.?${}*+') #匹配任何非字母数字字符 28 print(ret) #['.', '?', '$', '{', '}', '*', '+'] 29 30 #这里要匹配单独的I, 31 ret=re.findall('I\b','hello I am LIST') #原理上是I后面有个空格匹配。可以匹配上 32 print(ret) #[] 但是匹配失败,为什么呢? 33 #解决办法一 34 ret=re.findall('I\\b','hello I am LIST') 35 print(ret) #['I'] 匹配成功 36 #解决办法二 37 ret=re.findall(r'I\b','hello I am LIST') 38 print(ret) #['I'] 匹配成功 39 40 #为什么呢? 41 # 因为\b本身就是特殊字符,我们要把它解释成他自己的意思,所以I\\b才是真正要匹配的 42 # 而对于r'I\b',这个r是RawString的意思,r只对其内的反斜杠起作用(注意单个 \ 的问题),这个r会自动将其内的\转义 43 44 #这里要匹配a\c 45 ret=re.findall('a\\c','abca\cabcd') #正常情况下我么会认为a\\c就能匹配到。 46 print(ret) #[] 匹配失败 47 48 # 为什么呢? 49 # 因为a\\c只是针对re的转义,没错,但是python解析器也认为\是转义字符,所以我们的匹配规则应该是a\\\\c 50 ret=re.findall('a\\\\c','abca\cabcd') #正常情况下我么会认为a\\c就能匹配到。 51 print(ret) #['a\\c'] 匹配成功 52 # 根据前面匹配I,我们可以这样做。 53 ret=re.findall(r'a\\c','abca\cabcd') #正常情况下我么会认为a\\c就能匹配到。 54 print(ret) #['a\\c'] 匹配成功
元字符之分组()以及元字符之|
1 import re 2 3 ret = re.findall(r'(ad)+', 'add') #匹配0个或1个ab 4 print(ret) #['ad'] 5 6 ret = re.findall('(ab)+123','ababab123') #匹配到末尾的ab123中的ab,只取分组中的内容 7 print(ret) #['ab'] 8 9 ret = re.findall('(?:ab)+123','ababab123') #findall的结果不是匹配的全部内容,而是组内的内容,?:可以让结果为匹配的全部内容 10 print(ret) #['ababab123'] 11 12 13 ret=re.search('(?P<id>\d{2})/(?P<name>\w{3})','23/com') 14 print(ret.group()) #23/com 15 print(ret.group('id')) #23 16 print(ret.group('name')) #com 17 18 19 # 元字符之| 20 ret=re.findall('compan(y|ies)','companiesasdfsadfcompanysadfasdaf') 21 print(ret) #['ies', 'y'] |是或的意思,结合分组,匹配ies或y 22 23 ret=re.findall('compan(?:y|ies)','companiesasdfsadfcompanysadfasdaf') 24 print(ret) #['companies', 'company'] |是或的意思,结合分组以及?: 匹配完整。

浙公网安备 33010602011771号