python高级
python高级
和is的使用
is
判断地址
比较两个引用是否指向了同一个对象(引用比较)
判断值
比较两个对象是否相等
深拷贝和浅拷贝
深拷贝
返回拷贝过的新对象
是对于一个对象所有层次的拷贝(递归)
浅拷贝
两个变量指向同一地址
是对于一个对象的顶层拷贝
拷贝的是引用
动态语言
运行时可以修改类和对象的内容,有__slots__约束属性值
生成器
generator
定义
在Python中,这种一边循环一边计算的机制,称为生成器
生成式
可对返回的值进行加工
yield
返回当前值,暂停
send
发送一个值
协程
两个方法交替执行,模拟多任务实现方式之一
迭代器
iterator
定义
迭代是访问集合元素的一种方式。
迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
可以使用for循环和next()
生成器是迭代器,迭代器不一定是生成器
判断是否可以迭代
引用一个集合的模块
from collections.abc import Iterable,Iterator
isinstance(listA, Iterator)
iter函数
可迭代对象转换为迭代器
装饰器
decorator
闭包
方法内部声明方法,内部方法引用外部方法的变量,外部方法返回内部的引用
定义
拓展函数功能的一种函数,
它的返回值也是一个函数,
可在不更改原方法的前提下给函数增加新功能。
结构
闭包+语法糖(@方法名)
功能
1. 引入日志
2. 函数执行时间统计
3. 执行函数前预备处理
4. 执行函数后清理功能
5. 权限校验等场景
6. 缓存
元类
type
type是类的类
type是类的抽象的描述
type可以动态创建类
格式type(类名,父类名称组成的元组、可为空,包含属性的字典、名称和值)
定义
元类是用来创建类的东西
metaclass
创建类时会自动访问元类的方法
功能
1. 拦截类的创建
2. 修改类
3. 返回修改之后的类
垃圾回收
import gc
导入垃圾回收模块:Garbage Collection
引用计数
import sys
sys.getrefcount()
intern机制
创建同样的多个对象时,python会引用intern机制,
让它只占用一个对象所占的内存空间,靠引用计数去维护何时释放
垃圾回收
gc.isenabled()
垃圾回收机制是否开启(默认是开启的)
gc.enable()
开启垃圾回收
gc.disable()
关闭垃圾回收
gc.collect()
手动回收垃圾
print(gc.garbage)
打印垃圾数据
gc.get_count()
获得垃圾计数器
阈值
gc.get_threshold()
获得阈值
gc.set_threshold(700,10,10)
设置阈值,默认是(700,10,10)
以引用计数为主,标记清除和分代收集为辅的垃圾回收机制
内建属性/
魔法函数
str
返回字符串,强调可读性
repr
返回字符串,强调准确性
str__与__repr
都返回字符串,前者面向用户,后者面向程序员
如果两者同时存在,str会覆盖repr,优先执行
dict
获得对象属性的字典键值信息
doc
类的文档/多行注释
bases
获得基类信息,结果为元组
class
获得对象的类
name
获得执行文件名字
file
获得文件路径
getattribute
from typing import Any
属性拦截器
注意不要调用自己
内建函数
range
范围
map
接收一个函数f和一个list,并通过把函数f依次作用在list的每个元素上,得到一个新的object并返回
filter
对指定序列执行过滤操作
reduce
from functools import reduce
对参数序列中元素进行累积
sorted
修改列表顺序,返回修改后的数据
functools
from functools import partial,wraps
partial
偏函数
将原来的函数传递默认值,生成新的函数
wraps
使用装饰器时,调用doc时会对测试结果有一些影响,
此时需要使用wraps函数
hashlib模块
import hashlib
hashlib.md5()
hashlib.sha1()
调试
打断点,Debug模式
多进程
进程
process
os.fork()
分叉,在Linux可用,不支持Windows
进程类
Process
from multiprocessing import Process
导入进程类
os.getpid
获得进程id
process.current_process()
获得当前进程对象
Process.init(self)
继承Process类,数据初始化
参数
group
参数未使用,值始终为None
target
target表示调用的方法,就是子进程要执行的任务
name
可以为子进程命名
args
元组,必须有逗号,如:args=("x",)
kwargs
字典,如:kwargs={"name":"x","age":18}
方法
start()
启动进程,并调用该子进程中的p.run()
run()
进程启动并运行的方法,就是它去调用target指定的函数
terminate()
强制终止进程
is_alive()
判断进程是否是“活着”的状态
join(timeout)
让主线程等待某一子进程结束,才继续执行主进程。(防止阻塞)
timeout是可选的超时时间,超过一个时间主进程就不等待了。
进程池
Pool
from multiprocessing import Pool
导入进程池
pool=Pool(2)
声明了一个含有两个进程的进程池pool
pool.apply(方法名)
同步执行
pool.apply_async(方法名)
异步执行
pool.join()
防止阻塞
pool.close()
关闭池子
队列
Queue
from multiprocessing import Queue
from queue import Queue
导入队列
queue=Queue(5)
声明了长度为5的队列queue
queue.put_nowait()
不等待添加
queue.put(block=False,timeout=5)
写队列,不等待,超时时间为5秒
queue.get(block=True,timeout=3)
读队列,等待,超时时间为3秒
/获得队头数据
queue.empty()
是否空队列
queue.full()
是否满了
queue.qsize()
元素个数
进程之间共享数据
from multiprocessing import Manager
通过Manager可以实现
多进程复制文件
if name"main":
main()
进程必须使用该语句才能运行
线程
threading
线程类
Threading
import threading
导入线程
threading.current_threading()
threading.currentThreading()
获得当前进程对象
threading.Thread.init(self)
继承Thread类,初始化数据
参数
group
参数未使用,值始终为None
target
target表示调用的方法,就是子进程要执行的任务
name
可以为子进程命名
args
元组,必须有逗号,如:args=("x",)
kwargs
字典,如:kwargs={"name":"x","age":18}
方法
start()
启动进程,并调用该子进程中的p.run()
run()
进程启动并运行的方法,就是它去调用target指定的函数
terminate()
强制终止进程
is_alive()
判断进程是否是“活着”的状态
join(timeout)
让主线程等待某一子进程结束,才继续执行主进程。(防止阻塞)
timeout是可选的超时时间,超过一个时间主进程就不等待了。
线程池
ThreadPoolExecutor
from concurrent.futures import ThreadPoolExecutor
导入线程池
pool=ThreadPoolExecutor()
声明了一个含有5个进程的线程池pool
pool.apply(方法名)
同步执行
pool.apply_async(方法名)
异步执行
pool.join()
防止阻塞
pool.shutdown()
关闭池子
pool.submit(task)
分配任务
线程之间共享全局变量
幽灵后台线程/守护线程
daemon
t1=threading.Thread(targent=task,daemon=True)
声明线程
默认 False:不受线程约束;
True:主线程结束,其他线程直接结束
线程的互斥
多个线程共享全局变量,会出现线程的互斥
互斥锁lock
lock=threading.Lock()
创建了一把线程锁
lock.acquire()
上锁
lock.release()
开锁
可以解决资源分配问题
死锁
在线程间共享多个资源的时候,如果两个线程分别占有一部分资源
并且同时等待对方的资源,就会造成死锁。
如何避免死锁
程序设计时尽量避免(银行家算法)
添加超时时间
线程消费者和生产者
队列:先进先出
栈:先进后出
Queue
在多线程通信之间扮演重要的角色
添加数据到队列中,使用put()方法
从队列中取数据,使用get()方法
判断队列中是否还有数据,使用qsize()方法
多线程
在多线程环境下,每个线程都有自己的数据。一个线程使用自己的局部变量比使用全局变量好,因为局部变量只有线程自己能看见,不会影响其他线程,而全局变量的修改必须加锁。
1.函数传参
2.使用全局字典的方法
3.使用ThreadLocal的方法
python网络编程
网络编程
TCP/IP协议
应用层/传输层/网际层(网络层)/网络接口层(链路层)
端口port
知名端口(0-1023)
80:HTTP服务
21:FTP服务
22:SSH服务
动态端口(1024-65535)
cmd netstat -ano
查看端口状态
IP地址
网络地址和主机地址
ABCDE五类
私有IP
127.0.0.1 本机IP地址
子网掩码
将某个IP地址划分成网络地址和主机地址两部分
socket套接字
family参数
AF_INET
IPv4协议
type参数
SOCK_STREAM
流式套接字
SOCK_DGRAM
数据包套接字
UDP
用户数据报协议
UDP是TCP/IP协议簇中的一种协议,能够完成不同机器上的程序间的数据通信
import socket/from socket import *
导入socket
soc=socket(AF_INET,SOCK_DGRAM)
创建套接字soc (2,2)
soc.sendto(data,(addr,port))
发送数据到指定地址
soc.bind("",port)
绑定本地信息:IP地址(127.0.0.1)和端口号
recv,addr=soc.recvfrom(1024)
等待接收数据、地址 1024表示接收的最大字节数
soc.close()
关闭套接字
udp聊天室
udp广播
soc.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)
TCP
传输控制协议
为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议
import socket/from socket import *
导入socket
soc=socket(AF_INET,SOCK_STREAM)
创建套接字soc (2,1)
soc.connect(serverAddr)
链接服务器
soc.sendto(data,(addr,port))
发送数据到指定地址
recv,addr=soc.recvfrom(1024)
等待接收数据、地址 1024表示接收的最大字节数
soc.bind("",port)
绑定本地信息:IP地址(127.0.0.1)和端口号
soc.listen(5)
监听5个客户端
newSoc,addr=soc.accept()
该用户链接的soc和地址
newSoc.close()
关闭套接字
soc.close()
关闭套接字
正则表达式
正则表达式(Regular Expression,简写regex/regexp/RE)。
通常被用来检索、替换那些符合某个模式(规则)的文本。
re模块/方法
import re
导入re模块
re.match(pattern, string, flags=0)
在字符串开头匹配pattern,如果匹配成功(可以是空字符串)返回对应的match对象,否则返回None。
re.search(pattern, string, flags=0)
扫描整个字符串string,找到与正则表达式pattern的第一个匹配(可以是空字符串),并返回一个对应的match对象。如果 没有匹配返回None.
re.fullmatch(pattern, string, flags=0)
string是否整个和pattern匹配,如果是返回对应的match对象,否则返回None。
re.findall(pattern, string, flags=0)
返回列表
re.split(pattern, string, maxsplit=0, flags=0)
返回分割列表
re.sub(pattern, repl, string, count=0, flags=0)
使用repl替换pattern匹配到的内容,最多匹配count次
re.finditer(pattern, string, flags=0)
返回迭代器
re.compile(pattern, flags=0)
编译得到匹配模型
flags
re.I/re.IGNORECASE
匹配中大小写不敏感
re.M/re.MULTILINE
"^"匹配字符串开始和"\n"之后;"$"匹配"\n"之前和字符串末尾。
通常称为多行模式
re.S/re.DOTALL
"."匹配任意字符,包括换行符。
通常称为单行模式
如果要同时使用单行模式和多行模式,只需要将函数的可选参数flags设置为re.I|re.S即可。
单个字符
[]
匹配[]中列举的字符
\d
匹配数字,即0-9
\D
匹配非数字
\s
匹配空白,即空格,tab键
\S
匹配非空白
\w
匹配单词字符,即a-z,A-Z,0-9
\W
匹配非单词字符
贪婪字符
正则默认匹配贪婪模式,即匹配尽可能多个字符
在+、*、{m}之后加?开启非贪婪模
式
表示数量
.
匹配任意1个字符(除了\n)(单行模式合一匹配)
*
匹配前一个字符出现0次或无限次,即可有可无
+
匹配前一个字符出现1次或无限次,即至少有一次
?
匹配前一个字符出现1次或0次,即要么有一次,要么没有
{m}
匹配前一个字符出现m次
{m,}
匹配前一个字符至少出现m次
{m,n}
匹配前一个字符出现从m次到n次
表示边界
^
匹配字符串开头
$
匹配字符串结尾
\b
匹配一个单词的边界(字与空格间的位置)
\B
匹配非单词边界
原始字符串
字符串前加"r"表示原生字符串
""作为转义字符
匹配分组
|
匹配左右任意一个表达式
(ab)
将括号中字符作为一个分组
\num
引用分组num中匹配到的字符串
(?P
分组起别名 引用别名为name分组匹配到的字符串
常用正则表达式
见:py正则-总结
python高级
== 和 is 的使用
i s
判断地址
比较两个引用是否指向了同一个对象(引用比较)
==
判断值
比较两个对象是否相等
深拷贝和浅拷贝
深拷贝
返回拷贝过的新对象
是对于一个对象所有层次的拷贝(递归)
浅拷贝
两个变量指向同一地址
是对于一个对象的顶层拷贝
拷贝的是引用
动态语言
运行时可以修改类和对象的内容,有__slots__约束属性值
生成器
generator
定义
在Python中,这种一边循环一边计算的机制,称为生成器
生成式
可对返回的值进行加工
yield
返回当前值,暂停
send
发送一个值
协程
两个方法交替执行,模拟多任务实现方式之一
迭代器
iterator
定义
迭代是访问集合元素的一种方式。
迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
可以使用for循环和next()
生成器是迭代器,迭代器不一定是生成器
判断是否可以迭代
引用一个集合的模块
from collections.abc import Iterable,Iterator
isinstance(listA, Iterator)
iter函数
可迭代对象转换为迭代器
装饰器
decorator
闭包
方法内部声明方法,内部方法引用外部方法的变量,外部方法返回内部的引用
定义
拓展函数功能的一种函数,
它的返回值也是一个函数,
可在不更改原方法的前提下给函数增加新功能。
结构
闭包+语法糖(@方法名)
功能
1. 引入日志
2. 函数执行时间统计
3. 执行函数前预备处理
4. 执行函数后清理功能
5. 权限校验等场景
6. 缓存
元类
type
type是类的类
type是类的抽象的描述
type可以动态创建类
格式type(类名,父类名称组成的元组、可为空,包含属性的字典、名称和值)
定义
元类是用来创建类的东西
metaclass
创建类时会自动访问元类的方法
功能
1. 拦截类的创建
2. 修改类
3. 返回修改之后的类
垃圾回收
import gc
导入垃圾回收模块:Garbage Collection
引用计数
import sys
sys.getrefcount()
intern机制
创建同样的多个对象时,python会引用intern机制,
让它只占用一个对象所占的内存空间,靠引用计数去维护何时释放
垃圾回收
gc.isenabled()
垃圾回收机制是否开启(默认是开启的)
gc.enable()
开启垃圾回收
gc.disable()
关闭垃圾回收
gc.collect()
手动回收垃圾
print(gc.garbage)
打印垃圾数据
gc.get_count()
获得垃圾计数器
阈值
gc.get_threshold()
获得阈值
gc.set_threshold(700,10,10)
设置阈值,默认是(700,10,10)
以引用计数为主,标记清除和分代收集为辅的垃圾回收机制
内建属性/
魔法函数
str
返回字符串,强调可读性
repr
返回字符串,强调准确性
str__与__repr
都返回字符串,前者面向用户,后者面向程序员
如果两者同时存在,str会覆盖repr,优先执行
dict
获得对象属性的字典键值信息
doc
类的文档/多行注释
bases
获得基类信息,结果为元组
class
获得对象的类
name
获得执行文件名字
file
获得文件路径
getattribute
from typing import Any
属性拦截器
注意不要调用自己
内建函数
range
范围
map
接收一个函数f和一个list,并通过把函数f依次作用在list的每个元素上,得到一个新的object并返回
filter
对指定序列执行过滤操作
reduce
from functools import reduce
对参数序列中元素进行累积
sorted
修改列表顺序,返回修改后的数据
functools
from functools import partial,wraps
partial
偏函数
将原来的函数传递默认值,生成新的函数
wraps
使用装饰器时,调用doc时会对测试结果有一些影响,
此时需要使用wraps函数
hashlib模块
import hashlib
hashlib.md5()
hashlib.sha1()
调试
打断点,Debug模式
多进程
进程
process
os.fork()
分叉,在Linux可用,不支持Windows
进程类
Process
from multiprocessing import Process
导入进程类
os.getpid
获得进程id
process.current_process()
获得当前进程对象
Process.init(self)
继承Process类,数据初始化
参数
group
参数未使用,值始终为None
target
target表示调用的方法,就是子进程要执行的任务
name
可以为子进程命名
args
元组,必须有逗号,如:args=("x",)
kwargs
字典,如:kwargs={"name":"x","age":18}
方法
start()
启动进程,并调用该子进程中的p.run()
run()
进程启动并运行的方法,就是它去调用target指定的函数
terminate()
强制终止进程
is_alive()
判断进程是否是“活着”的状态
join(timeout)
让主线程等待某一子进程结束,才继续执行主进程。(防止阻塞)
timeout是可选的超时时间,超过一个时间主进程就不等待了。
进程池
Pool
from multiprocessing import Pool
导入进程池
pool=Pool(2)
声明了一个含有两个进程的进程池pool
pool.apply(方法名)
同步执行
pool.apply_async(方法名)
异步执行
pool.join()
防止阻塞
pool.close()
关闭池子
队列
Queue
from multiprocessing import Queue
from queue import Queue
导入队列
queue=Queue(5)
声明了长度为5的队列queue
queue.put_nowait()
不等待添加
queue.put(block=False,timeout=5)
写队列,不等待,超时时间为5秒
queue.get(block=True,timeout=3)
读队列,等待,超时时间为3秒
/获得队头数据
queue.empty()
是否空队列
queue.full()
是否满了
queue.qsize()
元素个数
进程之间共享数据
from multiprocessing import Manager
通过Manager可以实现
多进程复制文件
if name
main()
进程必须使用该语句才能运行
线程
threading
线程类
Threading
import threading
导入线程
threading.current_threading()
threading.currentThreading()
获得当前进程对象
threading.Thread.init(self)
继承Thread类,初始化数据
参数
group
参数未使用,值始终为None
target
target表示调用的方法,就是子进程要执行的任务
name
可以为子进程命名
args
元组,必须有逗号,如:args=("x",)
kwargs
字典,如:kwargs={"name":"x","age":18}
方法
start()
启动进程,并调用该子进程中的p.run()
run()
进程启动并运行的方法,就是它去调用target指定的函数
terminate()
强制终止进程
is_alive()
判断进程是否是“活着”的状态
join(timeout)
让主线程等待某一子进程结束,才继续执行主进程。(防止阻塞)
timeout是可选的超时时间,超过一个时间主进程就不等待了。
线程池
ThreadPoolExecutor
from concurrent.futures import ThreadPoolExecutor
导入线程池
pool=ThreadPoolExecutor()
声明了一个含有5个进程的线程池pool
pool.apply(方法名)
同步执行
pool.apply_async(方法名)
异步执行
pool.join()
防止阻塞
pool.shutdown()
关闭池子
pool.submit(task)
分配任务
线程之间共享全局变量
幽灵后台线程/守护线程
daemon
t1=threading.Thread(targent=task,daemon=True)
声明线程
默认 False:不受线程约束;
True:主线程结束,其他线程直接结束
线程的互斥
多个线程共享全局变量,会出现线程的互斥
互斥锁lock
lock=threading.Lock()
创建了一把线程锁
lock.acquire()
上锁
lock.release()
开锁
可以解决资源分配问题
死锁
在线程间共享多个资源的时候,如果两个线程分别占有一部分资源
并且同时等待对方的资源,就会造成死锁。
如何避免死锁
程序设计时尽量避免(银行家算法)
添加超时时间
线程消费者和生产者
队列:先进先出
栈:先进后出
Queue
在多线程通信之间扮演重要的角色
添加数据到队列中,使用put()方法
从队列中取数据,使用get()方法
判断队列中是否还有数据,使用qsize()方法
多线程
在多线程环境下,每个线程都有自己的数据。一个线程使用自己的局部变量比使用全局变量好,因为局部变量只有线程自己能看见,不会影响其他线程,而全局变量的修改必须加锁。
1.函数传参
2.使用全局字典的方法
3.使用ThreadLocal的方法
python网络编程
网络编程
TCP/IP协议
应用层/传输层/网际层(网络层)/网络接口层(链路层)
端口port
知名端口(0-1023)
80:HTTP服务
21:FTP服务
22:SSH服务
动态端口(1024-65535)
cmd netstat -ano
查看端口状态
IP地址
网络地址和主机地址
ABCDE五类
私有IP
127.0.0.1 本机IP地址
子网掩码
将某个IP地址划分成网络地址和主机地址两部分
socket套接字
family参数
AF_INET
IPv4协议
type参数
SOCK_STREAM
流式套接字
SOCK_DGRAM
数据包套接字
UDP
用户数据报协议
UDP是TCP/IP协议簇中的一种协议,能够完成不同机器上的程序间的数据通信
import socket/from socket import *
导入socket
soc=socket(AF_INET,SOCK_DGRAM)
创建套接字soc (2,2)
soc.sendto(data,(addr,port))
发送数据到指定地址
soc.bind("",port)
绑定本地信息:IP地址(127.0.0.1)和端口号
recv,addr=soc.recvfrom(1024)
等待接收数据、地址 1024表示接收的最大字节数
soc.close()
关闭套接字
udp聊天室
udp广播
soc.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)
TCP
传输控制协议
为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议
import socket/from socket import *
导入socket
soc=socket(AF_INET,SOCK_STREAM)
创建套接字soc (2,1)
soc.connect(serverAddr)
链接服务器
soc.sendto(data,(addr,port))
发送数据到指定地址
recv,addr=soc.recvfrom(1024)
等待接收数据、地址 1024表示接收的最大字节数
soc.bind("",port)
绑定本地信息:IP地址(127.0.0.1)和端口号
soc.listen(5)
监听5个客户端
newSoc,addr=soc.accept()
该用户链接的soc和地址
newSoc.close()
关闭套接字
soc.close()
关闭套接字
正则表达式
正则表达式(Regular Expression,简写regex/regexp/RE)。
通常被用来检索、替换那些符合某个模式(规则)的文本。
re模块/方法
import re
导入re模块
re.match(pattern, string, flags=0)
在字符串开头匹配pattern,如果匹配成功(可以是空字符串)返回对应的match对象,否则返回None。
re.search(pattern, string, flags=0)
扫描整个字符串string,找到与正则表达式pattern的第一个匹配(可以是空字符串),并返回一个对应的match对象。如果 没有匹配返回None.
re.fullmatch(pattern, string, flags=0)
string是否整个和pattern匹配,如果是返回对应的match对象,否则返回None。
re.findall(pattern, string, flags=0)
返回列表
re.split(pattern, string, maxsplit=0, flags=0)
返回分割列表
re.sub(pattern, repl, string, count=0, flags=0)
使用repl替换pattern匹配到的内容,最多匹配count次
re.finditer(pattern, string, flags=0)
返回迭代器
re.compile(pattern, flags=0)
编译得到匹配模型
flags
re.I/re.IGNORECASE
匹配中大小写不敏感
re.M/re.MULTILINE
"^"匹配字符串开始和"\n"之后;"$"匹配"\n"之前和字符串末尾。
通常称为多行模式
re.S/re.DOTALL
"."匹配任意字符,包括换行符。
通常称为单行模式
如果要同时使用单行模式和多行模式,只需要将函数的可选参数flags设置为re.I|re.S即可。
单个字符
[]
匹配[]中列举的字符
\d
匹配数字,即0-9
\D
匹配非数字
\s
匹配空白,即空格,tab键
\S
匹配非空白
\w
匹配单词字符,即a-z,A-Z,0-9
\W
匹配非单词字符
贪婪字符
正则默认匹配贪婪模式,即匹配尽可能多个字符
在+、*、{m}之后加?开启非贪婪模
式
表示数量
.
匹配任意1个字符(除了\n)(单行模式合一匹配)
*
匹配前一个字符出现0次或无限次,即可有可无
+
匹配前一个字符出现1次或无限次,即至少有一次
?
匹配前一个字符出现1次或0次,即要么有一次,要么没有
{m}
匹配前一个字符出现m次
{m,}
匹配前一个字符至少出现m次
{m,n}
匹配前一个字符出现从m次到n次
表示边界
^
匹配字符串开头
$
匹配字符串结尾
\b
匹配一个单词的边界(字与空格间的位置)
\B
匹配非单词边界
原始字符串
字符串前加"r"表示原生字符串
""作为转义字符
匹配分组
|
匹配左右任意一个表达式
(ab)
将括号中字符作为一个分组
\num
引用分组num中匹配到的字符串
(?P
分组起别名 引用别名为name分组匹配到的字符串
常用正则表达式
见:py正则-总结