常用模块

一、time模块

1、time模块中表示时间的格式:
(1)timestamp时间戳,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量
(2)format time 格式化时间,已格式化的结构使时间更具可读性。包括自定义格式和固定格式。
(3)struct_time时间元组,共有九个元素组。如下表:

索引属性
0tm_year(年)如2019
1tm_mon(月)1--2
2tm_day(日)1--31
3tm_hour(时)0--23
4tm_min(分)0--60
5tm_sec(秒)0--60
6tm_wday(weekday)0--6(0表示周日)
7tm_yday(一年中的第几天)1--366
8tm_isdst(是否是夏令时)默认为-1

2、时间格式相互转换:
在这里插入图片描述
3、time模块语法

(1)获取struct_time时间元组

data = time.time()
a = time.localtime(data)   # 将一个时间戳转换为当前时区的struct_time。()中参数未提供,则以当前时间为准。
b = time.gmtime(data)      # 和localtime()方法类似,gmtime()方法是将一个时间戳转换为UTC时区(0时区)的struct_time。
print(a)  
print(b)
# a的打印结果:time.struct_time(tm_year=2019, tm_mon=2, tm_mday=23, tm_hour=21, tm_min=32, tm_sec=32, tm_wday=5,  tm_yday=54, tm_isdst=0)
# b的打印结果:time.struct_time(tm_year=2019, tm_mon=2, tm_mday=23, tm_hour=13, tm_min=32, tm_sec=32, tm_wday=5, tm_yday=54, tm_isdst=0)

由上面两种打印结果来看time.localtime()和time.gmtime()两种方式获取的时间元组结果可能不一样,因为localtime时获取时间元组是按照当前所处的时区来计算的,而gmtime是按照0时区来计算的,因而要根据需要来选择哪种获取那个时区时间元组.

(2)获取时间戳

time_tuple = time.localtime()

a = time.time()                  # 获取当地当前的时间戳
b = time.mktime(time_tuple)      # 讲一个时间元组转换成时间戳

print(a)                         # 打印结果:1550929461.7366028
print(b)                         # 打印结果:1550929461.0

上述结果说明用time.time() 获取的时间戳,其精度可以达到毫秒级,而time.mktime()只能精确到秒。在使用time.time()获取时间戳时()里面必须为空,如果不为空则会报错,并且time.time(None)此种用法也会报错。而用time.mktime(tuple) 是将一个时间元组转换成时间戳,因而()里面不能为空,必须填一个时间元组,不填或者tuple=None程序都会报错。

(3)时间元组与时间戳相互转换

time_tuple = time.localtime()   # 时间元组
data = time.time()              # 时间戳
 
# 时间元组转换成时间戳

a = time.mktime(time_tuple)

# 时间戳转换成时间元组

b =  time.localtime(data)

print(a)
print(b)

(4)时间元组与时间字符串相互转换

time_str = '2019-2-23 22:03:00'  # 时间字符串

time_tuple = time.localtime()    # 时间元组

# 时间元组转换成时间字符串

a = time.strftime('%Y-%m-%d  %H:%M:%S',time_tuple)

# 时间字符串转换成时间元组

b =  time.strptime(time_str,'%Y-%m-%d  %H:%M:%S')

print(a)
print(b)

(5)time模块其他语法

# 英文显示时间字符串

c = time.asctime(time_tuple)

d = time.asctime()

print(c)               # 结果:Sat Feb 23 22:17:08 2019
print(d)               # 结果:Sat Feb 23 22:17:08 2019

# 将线程推迟指定的时间运行,单位为秒

befor = time.time()

f = time.sleep(5)       # 将下段代码执行时间推迟5秒后执行

now = time.time()

print(befor)      # 结果:1550931428.376828
print(now)		  # 结果:1550931433.376828

(6)字符串转时间格式对应表

索引符号意义
0%y两位数的年份表示(00-99)
1%Y四位数的年份表示(000-9999)
2%m月份(01-12)
3%d月内中的一天(0-31)
4%H24小时制小时数(0-23
5%I12小时制小时数(01-12)
6%M分钟数(00=59)
7%S 秒(00-59)
8%a本地简化星期名称
9%A本地完整星期名称
10%b 本地简化的月份名称
11%B本地完整的月份名称
12%c本地相应的日期表示和时间表示
13%j 年内的一天(001-366)
14%p 本地A.M.或P.M.的等价符
15%U 一年中的星期数(00-53)星期天为星期的开始
16%w 星期(0-6),星期天为星期的开始
17%W一年中的星期数(00-53)星期一为星期的开始
18%x 本地相应的日期表示
19%X本地相应的时间表示
20%Z 当前时区的名称
21%%%号本身

注意:时间字符串和成时间戳相互转换时,必须要先转换成时间元组

二、datetime模块

(1)datetime.date:表示日期的类。常用的属性有year, month, day;只关注日期

import datetime
# 获取当前日期
a = datetime.date.today()

# 时间替换
b = datetime.date.replace(a,year=1,month=2,day=3)

# 转换成时间字符串
c = datetime.date.strftime(a,'%y-%m-%d')

# 转换成时间元组
d = datetime.date.timetuple(a)


print(a)   # 结果:2019-02-23
print(b)   # 结果:0001-02-03
print(c)   # 结果:19-02-23
print(d)   #结果:time.struct_time(tm_year=2019, tm_mon=2, tm_mday=23, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=54, tm_isdst=-1)

(2)datetime.time:表示时间的类。常用的属性有hour, minute, second, microsecond。只关注时间

import datetime
da = datetime.time(19,2,23)     # 分别代表时,分,秒

a = datetime.time.strftime(da,'%H:%M:%S')

print(a)     # 结果:19:02:23

(3)datetime.datetime:表示日期时间,同时又日期和时间

import datetime
# 获取当前时间,精确到毫秒
da = datetime.datetime.now()

# 时间替换
a = datetime.datetime.replace(da,year=2000,month=12,day=23,hour=20,minute=45,microsecond=555)

print(da)    # 结果:2019-02-23 23:25:39.935206   
print(a)     # 结果:2000-12-23 20:45:39.000555

(4)datetime.timedelta:表示时间间隔,即两个时间点之间的长度。可以进行时间运算

import datetime
# 获取当前时间,精确到毫秒
da = datetime.datetime.now()

# 加减天数
a = da + datetime.timedelta(-1)

# 加减天数,小时和毫秒
b = da - datetime.timedelta(1,hours=2,microseconds=5)

print(da)      #结果:2019-02-23 23:33:57.040902
print(a)       #结果:2019-02-22 23:33:57.040902
print(b)	   #结果:2019-02-22 21:33:57.040897

(5)datetime.tzinfo:与时区有关的相关信息。

三、random模块

import random
import string

#取1-100间的随机数,包含100

a = random.randint(1,100)
print(a)                          
print(random.randint(1,100))

#取1-100间的随机数,不包含100

b = random.randrange(1,100)
print(b)

#从字符串里随意返回一个字符

c = random.choice('adjhfnbxh12wyt')
print(c)
print(random.choice('adjhfnbxh12wyt'))


#从字符串里随意返回指定数量的字符,以列表方式返回

d = random.sample('adjhfnbxh12wyt',3)

print(random.sample('adjhfnbxh12wyt',3))     # 随机结果:['h', '1', 'j']
print(random.sample('adjhfnbxh12wyt',2))     # 随机结果:['1', 't']


#生成随机验证码

s = string.ascii_lowercase + string.digits  #生成小写字母和数字组合的字符串
print(s)

''.join(random.sample(s,6))                 #生成6位随机验证码
print(''.join(random.sample(s,6)) )
print(''.join(random.sample(s,6)) )
print(''.join(random.sample(s,6)) )


#洗牌,输出列表

x = list(range(20))
print(x)

random.shuffle(x)

print(x)

四、OS模块

os模块是与操作系统交互的一个接口
1.不含path的命令
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir(“dirname”) 改变当前脚本工作目录;相当于shell下cd
os.curdir 返回当前目录: (’.’)
os.pardir 获取当前目录的父目录字符串名:(’…’)
os.makedirs(‘dirname1/dirname2’) 可生成多层递归目录
os.removedirs(‘dirname1’) 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推,直至非空目录
os.mkdir(‘dirname’) 生成单级目录;相当于shell中mkdir dirname
os.rmdir(‘dirname’) 删除单级空目录(最后一层目录),若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir(‘dirname’) 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove() 删除一个文件
os.rename(“oldname”,“newname”) 重命名文件/目录
os.stat(‘path/filename’) 获取文件/目录信息
os.sep 输出操作系统特定的路径分隔符,win下为"",Linux下为"/"
os.linesep 输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep 输出用于分割文件路径的字符串 win下为;,Linux下为:
os.name 输出字符串指示当前使用平台。win->‘nt’; Linux->‘posix’
os.system(“bash command”) 运行shell命令,直接显示
os.popen("bash command) 运行shell命令,获取执行结果
os.environ 获取系统环境变量
2.含path的命令

os.path.abspath(path) 返回path规范化的绝对路径 os.path.split(path) 将path分割成目录和文件名二元组返回 os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素 os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素

os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path) 如果path是绝对路径,返回True
os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, …]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path) 返回path所指向的文件或者目录的最后访问时间
os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间
os.path.getsize(path) 返回path的大小

五、sys模块

sys模块是与python解释器交互的一个接口。

sys.argv 命令行参数List,第一个元素是程序本身路径
sys.exit(n) 退出程序,正常退出时exit(0)
sys.version 获取Python解释程序的版本信息
sys.maxint 最大的Int值
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称
sys.stdout.write(‘please:’) #标准输出 , 引出进度条的例子, 注,在py3上不行,可以用print代替
val = sys.stdin.readline()[:-1] #标准输入
sys.getrecursionlimit() #获取最大递归层数
sys.setrecursionlimit(1200) #设置最大递归层数
sys.getdefaultencoding() #获取解释器默认编码
sys.getfilesystemencoding #获取内存数据存到文件里的默认编码
sys.modules 是一个全局字典,该字典是python启动后就加载在内存中。每当程序员导入新的模块,sys.modules将自动记录该模块。当第二次再导入该模块时,python会直接到字典中查找,从而加快了程序运行的速度。它拥有字典所拥有的一切方法。

六、序列化

序列化是指把内存里的数据类型转变成字符串,以使其能存储到硬盘或通过网络传输到远程,因为硬盘或网络传输时只能接受bytes。
序列化目的:
1、以某种存储形式使自定义对象持久化;
2、将对象从一个地方传递到另一个地方。
3、使程序更具维护性
在这里插入图片描述

pickle模块
pickle是python中独有的序列化模块,是指不能和其他编程语言的序列化进行交互,因为pickle将数据对象转化为bytes
pickle模块提供了四个功能:dumps、dump、loads、load。
dumps和dump都是进行序列化,而loads和load则是反序列化。

dumps将所传入的变量的值序列化为一个bytes,然后,就可以将这个bytes写入磁盘或者进行传输。

import pickle
list = [1,2,3,'d']
str1 = pickle._dumps(list)
print(str1)                # 结果:b'\x80\x03]q\x00(K\x01K\x02K\x03X\x01\x00\x00\x00dq\x01e.'

lis = pickle.loads(str1)
print(lis)                 # 结果:[1,2,3,'d']

而dump则更加一步到位,在dump中可以传入两个参数,一个为需要序列化的变量,另一个为需要写入的文件。

import pickle
list = [1,2,3,'d']
data = {'k1':123,'k2':'Hello'}

f = open('dump.pkl','wb')
str_dumps = pickle.dump(list,f)
f.close()


f2 = open('dump.pkl','rb')
list_loads = pickle.load(f2)

print(list_loads)            # 结果: [1,2,3,'d']             

json模块
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
json中的方法和pickle中差不多,也是dumps,dump,loads,load。使用上也没有什么区别,区别在于,json中的序列化后格式为字符。

import json

lis_str = json.dumps(list)
print(lis_str)
print(type(lis_str))

lis = json.loads(lis_str)
print(lis)
print(type(lis))

f = open('str.json','w',encoding='utf-8')
json.dump(list,f)

f2 = open('str.json','r',encoding='utf-8')

a = json.load(f2)
print(a)

json和pickle区别:
json:
优点:跨语言、体积小

缺点:只能支持int\str\list\tuple\dict

Pickle:

优点:专为python设计,支持python所有的数据类型

缺点:只能在python中使用,存储数据占空间大

七、logging模块

python的logging模块提供了标准的日志接口,通过它存储各种格式的日志,logging的日志可以分为 debug(), info(), warning(), error() and critical()5个级别。

logging模块的日志可以定义很多种格式,如下表:

序号%(name)slogge名字
1%(levelno)s数字形式的日志级别
2%(levelname)s文本形式的日志级别
3%(pathname)s调用日志输出函数的模块的完整路径名,可能没有
4%(filename)s调用日志输出函数的模块的文件名
5%(module)s调用日志输出函数的模块名
6%(funcName)s调用日志输出函数的函数名
7%(lineno)d调用日志输出函数的语句所在的代码行
8%(created)f当前时间,用UNIX标准的表示时间的浮 点数表示
9%(relativeCreated)d输出日志信息时的,自Logger创建以 来的毫秒数
10%(asctime)s字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
11%(thread)d线程ID。可能没有
12%(threadName)s线程名。可能没有
13%(process)d进程ID。可能没有
14%(message)s用户输出的消息

Python 使用logging模块记录日志涉及四个主要类:

logger提供了应用程序可以直接使用的接口;每个程序在输出信息之前都要获得一个Logger。Logger通常对应了程序的模块名,比如聊天工具的图形界面模块可以这样获得它的Logger:
handler将(logger创建的)日志记录发送到合适的目的输出;
filter提供了细度设备来决定输出哪条日志记录;
formatter决定日志记录的最终输出格式。

他们之间的关系如下:
在这里插入图片描述

import logging
from logging import handlers  #导入日志截断模块


#创建fillter对象
class IgnoreBackupFilter(logging.Filter):
    def filter(self, record):
        return 'db backup' not in record.getMessage()   #将日志中带db backup的日志忽略掉


#生成 logger 对象

logger = logging.getLogger('web')

#把filtter对象添加到logger中

logger.addFilter(IgnoreBackupFilter())

#设置日志级别
logger.setLevel(logging.DEBUG)              # 一般对未输出的日志没有设置级别,则默认此处设置的日志级别;如果输出的日志级别比此处设置全局的日志级别还要低,则按照此处设置的全局日志级别进行输出

#生成 handler 对象

ch = logging.StreamHandler()                 # 输出日志到屏幕
fh = logging.FileHandler('web.log')          # 输出日志到文件中

#截取日志,按照每份日志的大小来保存,超出大小后重新生成新的日志
fh1 = handlers.RotatingFileHandler('web.log',maxBytes=10,backupCount=3) #(日志名称,没份日志大小,保存多少份日志)

#截取日志,按照时间来截取日志
fh2 = handlers.TimedRotatingFileHandler('web.log',when='s',interval= 2,backupCount=3)  #(名称,时间级数,时间长度,保存文件个数)

#设置输出日志的级别

ch.setLevel(logging.INFO)
fh.setLevel(logging.WARNING)

#把handler对象绑定到logger

logger.addHandler(ch)
logger.addHandler(fh)

#生成 formatter 对象
# 把formatter 对象绑定handler对象


file_formatter = logging.Formatter('%(asctime)s - %(levelno)s - %(filename)s  - %(message)s',
                                    datefmt='%Y-%m-%d %I:%M:%S %p')
console_formatter = logging.Formatter('%(asctime)s - %(levelno)s - %(filename)s  - %(message)s - %(lineno)d',
                                      datefmt='%Y-%m-%d %I:%M:%S %p')

ch.setFormatter(console_formatter)
fh.setFormatter(file_formatter)

logger.debug('love you')
logger.info('you love?')
logger.warning('Yes you love')
logger.debug('db backup not love')

日志重复输出优化

import logging
def my_log():
    logger = logging.getLogger('mysql.log')
	# 每次被调用后打印出logger的handlers列表
    print(logger.handlers)

    ch = logging.StreamHandler()
    ch.setLevel(logging.ERROR)
    fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    ch.setFormatter(fmt)
    logger.addHandler(ch)

    return logger

my_log().error('run one')
my_log().error('run two')
my_log().error('run three')

#输出结果:
019-02-24 23:59:23,150 - mysql.log - ERROR - run one
2019-02-24 23:59:23,150 - mysql.log - ERROR - run two
2019-02-24 23:59:23,150 - mysql.log - ERROR - run two
2019-02-24 23:59:23,150 - mysql.log - ERROR - run three
2019-02-24 23:59:23,150 - mysql.log - ERROR - run three
2019-02-24 23:59:23,150 - mysql.log - ERROR - run three
[]
[<StreamHandler <stderr> (ERROR)>]
[<StreamHandler <stderr> (ERROR)>, <StreamHandler <stderr> (ERROR)>]

从上面代码运行结果来看,在运行日志输出函数时日志重复了,并且数量成递增趋势,实际上时因为logger = logging.getLogger(‘mysql.log’)在执行时,没有每次生成一个新的logger,而是先检查内存中是否存在一个叫做‘mysql.log’的logger对象,存在则取出,不存在则新建。
1、logger.handlers最初是一个空列表,执行‘logger.addHandler(ch)’添加个‘StreamHandler’,输出一条日志

2、在第二次被调用时,logger.handlers已经存在一个‘StreamHandler’,再次执行‘logger.addHandler(ch)’就会再次添加一 个‘StreamHandler’,此时的logger有两个个‘StreamHandler’,输出两条重复的日志

3、在第三次被调用时,logger.handlers已经存在两个‘StreamHandler’,再次执行‘logger.addHandler(ch)’就会再次添加一个,此时的logger有三个‘StreamHandler’,输出三条重复的日志

解决办法:

# 及时清理(logger.handlers.clear)
def my_log():
    logger = logging.getLogger()
    # 每次被调用后,清空已经存在handler
    logger.handlers.clear()

    ch = logging.StreamHandler()
    ch.setLevel(logging.ERROR)
    fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    ch.setFormatter(fmt)

    logger.addHandler(ch)

    return logger

my_log().error('run one')
my_log().error('run two')
my_log().error('run three')

# 用前判断
import logging

def my_log():
    logger = logging.getLogger('mysql.log')
    # 判断logger是否已经添加过handler,是则直接返回logger对象,否则执行handler设定以及addHandler(ch)
    if not logger.handlers:
        ch = logging.StreamHandler()
        ch.setLevel(logging.ERROR)
        fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        ch.setFormatter(fmt)

        logger.addHandler(ch)

    return logger

my_log().error('run one')
my_log().error('run two')
my_log().error('run three')

八、re模块

正则表达式就是字符串的匹配规则,一种小型的、高度专业化的编程语言,而在python中,通过内嵌集成re模块。

1、普通字符和11个元字符:

普通字符匹配自身
.匹配任意除换行符"\n"外的字符(在DOTALL模式中也能匹配换行符)
\转义字符,使后一个字符改变原来的意思
*匹配前一个字符0或多次
+匹配前一个字符1次或无限次
匹配一个字符0次或1次
^匹配字符串开头。在多行模式中匹配每一行的开头
$匹配字符串末尾,在多行模式中匹配每一行的末尾
|或。匹配|左右表达式任意一个,从左到右匹配,如果|没有包括在()中,则它的范围是整个正则表达式
{}{m}匹配前一个字符m次,{m,n}匹配前一个字符m至n次,若省略n,则匹配m至无限次
[]字符集。对应的位置可以是字符集中任意字符。字符集中的字符可以逐个列出,也可以给出范围,如[abc]或[a-c]。[^abc]表示取反,即非abc。所有特殊字符在字符集中都失去其原有的特殊含义。用\反斜杠转义恢复特殊字符的特殊含义。
()被括起来的表达式将作为分组,从表达式左边开始没遇到一个分组的左括号“(”,编号+1.分组表达式作为一个整体,可以后接数量词。表达式中的|仅在该组中有效。

这里需要强调一下反斜杠\的作用:

反斜杠后边跟元字符去除特殊功能;(即将特殊字符转义成普通字符)
反斜杠后边跟普通字符实现特殊功能;(即预定义字符)
引用序号对应的字组所匹配的字符串。

2、预定义字符

预定义字符匹配自身
\d数字:[0-9]
\D非数字:[^\d]
\s匹配任何空白字符:[<空格>\t\r\n\f\v]
\S非空白字符:[^\s]
\w匹配包括下划线在内的任何字字符:[A-Za-z0-9_]
\W匹配非字母字符,即匹配特殊字符
\A仅匹配字符串开头,同^
\Z仅匹配字符串结尾,同$
\b匹配\w和\W之间,即匹配单词边界匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B[^\b]

3、特殊分组

预定义字符匹配自身
(?P)分组,除了原有的编号外再指定一个额外的别名
(?P=name)引用别名为的分组匹配到字符串

4、re的匹配语法

re.compile()
编译正则表达式模式,返回一个对象的模式。(可以把那些常用的正则表达式编译成正则表达式对象,这样可以提高一点效率。)

格式:re.compile(pattern,flags=0)

pattern: 编译时用的表达式字符串。

import re
tt = "Tina is a good girl, she is cool, clever, and so on..."
rr = re.compile(r'\w*oo\w*')
print(rr.findall(tt))   #查找所有包含'oo'的单词
执行结果如下:
['good', 'cool']

re.match(pattern, string, flags=0)

从起始位置开始根据模型去字符串中匹配指定内容,匹配单个

pattern 正则表达式
string 要匹配的字符串
flags 标志位,用于控制正则表达式的匹配方式

import re
print(re.match('com','comwww.runcomoob').group())
print(re.match('com','Comwww.runcomoob',re.I).group())
执行结果如下:
com
com

flags 编译标志位,用于修改正则表达式的匹配方式,如:是否区分大小写,多行匹配等。常用的flags有:

标志含义
re.S(DOTALL)使.匹配包括换行在内的所有字符
re.I(IGNORECASE)忽略大小写(括号内是完整写法,下同)
re.L(LOCALE)做本地化识别(locale-aware)匹配,法语等
re.M(MULTILINE)多行匹配,改变'^'和'$'的行为
re.X(VERBOSE)可以给你的表达式写注释,使其更可读
re.U根据Unicode字符集解析字符,这个标志影响\w,\W,\b,\B

re.search(pattern, string, flags=0)

re.search函数会在字符串内查找模式匹配,只要找到第一个匹配然后返回,如果字符串没有匹配,则返回None。

import re
print(re.search('\dcom','www.4comrunoob.5com').group())
执行结果如下:
4com

re.findall(pattern, string, flags=0)

match and search均用于匹配单值,即:只能匹配字符串中的一个,如果想要匹配到字符串中所有符合条件的元素,则需要使用 findall。

import re
p = re.compile(r'\d+')
print(p.findall('o1n2m3k4'))
执行结果如下:
['1', '2', '3', '4']

re.sub(pattern, repl, string, count=0, flags=0)

用于替换匹配的字符串

import re
c = 'aa12bb33dd55#ffg-df|dX32fd'

print(re.sub('\d+','_',c,count=2))

执行结果如下:
aa_bb_dd55#ffg-df|dX32fd

re.split(pattern, string, maxsplit=0, flags=0)
maxsplit用于指定最大分割次数,不指定将全部分割。

import re
c = 'aa12bb33dd55#ffg-df|dX32fd'
print(re.split('\d+|#|-|\|',c))     #\|将|的语法转换成字符|

执行结果如下:
['aa', 'bb', 'dd', '', 'ffg', 'df', 'dX', 'fd']

re.fullmatch(pattern, string, flags=0)

整个字符串匹配成功就返回re object, 否则返回None

import re
print(re.fullmatch('\w+@\w+\.(com|cn|edu)',"alex@oldboyedu.cn"))
执行结果:
<re.Match object; span=(0, 17), match='alex@oldboyedu.cn'>

注意:
match和search一旦匹配成功,就是一个match object对象,而match object对象有以下方法:
group() 返回被 RE 匹配的字符串
start() 返回匹配开始的位置
end() 返回匹配结束的位置
span() 返回一个元组包含匹配 (开始,结束) 的位置
groups() 返回re整体匹配的字符串,可以一次输入多个组号,对应组号匹配的字符串。以元组形式返回
groupdict() 将匹配到的结果以字典形式返回,与分组匹配搭配使用

import re
s='41125119910516****'
b = re.search('(?P<province>\d{3})(?P<city>\d{3})(?P<born_year>\d{4})',s)
print(b)
print(b.groups())
print(b.groupdict())
执行结果:
<re.Match object; span=(0, 10), match='4112511991'>
('411', '251', '1991')
{'province': '411', 'city': '251', 'born_year': '1991'}

re.match与re.search与re.findall的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。

贪婪匹配与非贪婪匹配
?, +? ,??, {m,n}? 前面的,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配

import re
a = re.findall(r"a(\d+?)",'a23b')
print(a)
b = re.findall(r"a(\d+)",'a23b')
print(b)
执行结果:
['2']
['23']

使用re模块下的findall()函数的问题

import re

string="abcdefg  acbdgef  abcdgfe  cadbgfe"

#带括号与不带括号的区别
#不带括号
regex=re.compile("((\w+)\s+\w+)")
print(regex.findall(string))
#输出:[('abcdefg  acbdgef', 'abcdefg'), ('abcdgfe  cadbgfe', 'abcdgfe')]

regex1=re.compile("(\w+)\s+\w+")
print(regex1.findall(string))
#输出:['abcdefg', 'abcdgfe']

regex2=re.compile("\w+\s+\w+")
print(regex2.findall(string))
#输出:['abcdefg  acbdgef', 'abcdgfe  cadbgfe']

# 第一个 regex 中是带有2个括号的,我们可以看到其输出是一个list 中包含2个 tuple 

# 第二个 regex 中带有1个括号,其输出的内容就是括号匹配到的内容,而不是整个表达式所匹配到的结果。

# 第三个 regex 中不带有括号,其输出的内容就是整个表达式所匹配到的内容。

结论:findall()返回的是括号所匹配到的结果(如regex1),多个括号就会返回多个括号分别匹配到的结果(如regex),如果没有括号就返回就返回整条语句所匹配到的结果(如regex2)。所以在提取数据的时候就需要注意。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值