部分模块

什么是模块?

常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。

但其实import加载的模块分为四个通用类别: 

  1 使用python编写的代码(.py文件)

  2 已被编译为共享库或DLL的C或C++扩展

  3 包好一组模块的包

  4 使用C编写并链接到python解释器的内置模块

为何要使用模块?

如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script。

随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用,

常用模块

                                                                                                                     时间模块

和时间有关系的我们就要用到时间模块。在使用模块之前,应该首先导入这个模块。

#常用方法
1.time.sleep(secs)
(线程)推迟指定的时间运行。单位为秒。
2.time.time()
获取当前时间戳

表示时间的三种方式

在Python中,通常有这三种方式来表示时间:时间戳、元组(struct_time)、格式化的时间字符串:

(1)时间戳(timestamp) :通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。

(2)格式化的时间字符串(Format String): ‘1999-12-06’

(3)元组(struct_time) :struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天等)

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

首先,我们先导入time模块,来认识一下python中表示时间的几种格式:

#导入时间模块
import time

#时间戳
time.time()
1500875844.800804

#时间字符串
time.strftime("%Y-%m-%d %X")
‘2017-07-24 13:54:37‘     #今天的日期
time.strftime("%Y-%m-%d %H-%M-%S")
‘2017-07-24 13-55-04‘    #2017年7月24号13点55分04秒

#时间元组:localtime将一个时间戳转换为当前时区的struct_time
time.localtime()
time.struct_time(tm_year=2017, tm_mon=7, tm_mday=24,
          tm_hour=13, tm_min=59, tm_sec=37,
                 tm_wday=0, tm_yday=205, tm_isdst=0)

小结:时间戳是计算机能够识别的时间;时间字符串是人能够看懂的时间;元组则是用来操作时间的

几种格式之间的转换

#时间戳-->结构化时间
#time.gmtime(时间戳)    #UTC时间,格林威治时间,地球的0时区,标准时间
#time.localtime(时间戳) #当地时间。例如我们现在在北京执行这个方法:与UTC时间相差8小时,UTC时间+8小时 = 北京时间
time.gmtime(1500000000)
time.struct_time(tm_year=2017, tm_mon=7, tm_mday=14, tm_hour=2, tm_min=40, tm_sec=0, tm_wday=4, tm_yday=195, tm_isdst=0)
time.localtime(1500000000)
time.struct_time(tm_year=2017, tm_mon=7, tm_mday=14, tm_hour=10, tm_min=40, tm_sec=0, tm_wday=4, tm_yday=195, tm_isdst=0)

#结构化时间-->时间戳 
#time.mktime(结构化时间)
time_tuple = time.localtime(1500000000)
print(time.mktime(time_tuple))
1500000000.0
#结构化时间-->字符串时间
#time.strftime("格式定义","结构化时间")  结构化时间参数若不传,则现实当前时间
time.strftime("%Y-%m-%d %X")
‘2017-07-24 14:55:36‘
time.strftime("%Y-%m-%d",time.localtime(1500000000))
‘2017-07-14‘

#字符串时间-->结构化时间
#time.strptime(时间字符串,字符串对应格式)
time.strptime("2017-03-16","%Y-%m-%d")
time.struct_time(tm_year=2017, tm_mon=3, tm_mday=16, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=75, tm_isdst=-1)
time.strptime("07/24/2017","%m/%d/%Y")
time.struct_time(tm_year=2017, tm_mon=7, tm_mday=24, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=0, tm_yday=205, tm_isdst=-1)

#结构化时间 --> %a %b %d %H:%M:%S %Y串
#time.asctime(结构化时间) 如果不传参数,直接返回当前时间的格式化串
time.asctime(time.localtime(1500000000))
‘Fri Jul 14 10:40:00 2017‘
time.asctime()
‘Mon Jul 24 15:18:33 2017‘

#%a %d %d %H:%M:%S %Y串 --> 结构化时间
#time.ctime(时间戳)  如果不传参数,直接返回当前时间的格式化串
time.ctime()
‘Mon Jul 24 15:19:07 2017‘
time.ctime(1500000000)
‘Fri Jul 14 10:40:00 2017‘ 

计算时间差的标准公式
import time
true_time=time.mktime(time.strptime(‘2017-09-11 08:30:00‘,‘%Y-%m-%d %H:%M:%S‘))

time_now=time.mktime(time.strptime(‘2017-09-12 11:00:00‘,‘%Y-%m-%d %H:%M:%S‘))

dif_time=time_now-true_time

struct_time=time.gmtime(dif_time)

print(‘过去了%d年%d月%d天%d小时%d分钟%d秒‘%(struct_time.tm_year-1970,struct_time.tm_mon-1,
struct_time.tm_mday-1,struct_time.tm_hour,
struct_time.tm_min,struct_time.tm_sec))

                                                                                           

                                                                                                           random模块

import random
#随机小数
random.random()      # 大于0且小于1之间的小数
0.7664338663654585
random.uniform(1,5) #大于1小于5的小数,括号里的数字是元素范围
1.6270147180533838

#随机整数random.randint(1,5)  # 大于等于1且小于等于5之间的整数
random.randrange(1,10,2) # 大于等于1且小于10之间的奇数,后面的2是随机步长

#随机选择一个返回
random.choice([1,‘23‘,[4,5]])  # #1或者23或者[4,5]
#随机选择多个返回,返回的个数为函数的第二个参数
random.sample([1,‘23‘,[4,5]],2) # #列表元素任意2个组合,后面的2是组合数量
[[4, 5], ‘23‘]

#打乱列表顺序
l1=[1,3,5,7,9]
random.shuffle(l1) # 打乱次序
print(61)   #
[5, 1, 3, 7, 9]
random.shuffle(l1)
print(l1)
[5, 9, 7, 1, 3]

生成随机验证码

import random

def v_code():

    code = ‘‘
    for i in range(5):

        num=random.randint(0,9)
        alf=chr(random.randint(65,90))
        add=random.choice([num,alf])
        code="".join([code,str(add)])

    return code

print(v_code())

os模块

os模块     死记硬背就行

os模块是与操作系统交互的一个接口

‘‘‘
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  获取系统环境变量
os.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的大小
‘‘‘

注意:os.stat(‘path/filename‘)  获取文件/目录信息 的结构说明

stat 结构:

st_mode: inode 保护模式
st_ino: inode 节点号。
st_dev: inode 驻留的设备。
st_nlink: inode 的链接数。
st_uid: 所有者的用户ID。
st_gid: 所有者的组ID。
st_size: 普通文件以字节为单位的大小;包含等待某些特殊文件的数据。
st_atime: 上次访问的时间。
st_mtime: 最后一次修改的时间。
st_ctime: 由操作系统报告的"ctime"。在某些系统上(如Unix)是最新的元数据更改的时间,在其它系统上(如Windows)是创建时间(详细信息参见平台的文档)。

                                                                                                                                                        sys模块

sys.argv           命令行参数List,第一个元素是程序本身路径
sys.exit(n)        退出程序,正常退出时exit(0),错误退出sys.exit(1)
sys.version        获取Python解释程序的版本信息
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform       返回操作系统平台名称

异常处理和status

import sys
try:
    sys.exit(1)
except SystemExit as e:
    print(e)

                                                                                       序列化模块

什么叫序列化——将原本的字典、列表等内容转换成一个字符串的过程就叫做序列化。为什么要有序列化模块
比如,我们在python代码中计算的一个数据需要给另外一段程序使用,那我们怎么给?
现在我们能想到的方法就是存在文件里,然后另一个python程序再从文件里读出来。
但是我们都知道,对于文件来说是没有字典这个概念的,所以我们只能将数据转换成字典放到文件中。
你一定会问,将字典转换成一个字符串很简单,就是str(dic)就可以办到了,为什么我们还要学习序列化模块呢?
没错序列化的过程就是从dic 变成str(dic)的过程。现在你可以通过str(dic),将一个名为dic的字典转换成一个字符串,
但是你要怎么把一个字符串转换成字典呢?
聪明的你肯定想到了eval(),如果我们将一个字符串类型的字典str_dic传给eval,就会得到一个返回的字典类型了。
eval()函数十分强大,但是eval是做什么的?e官方demo解释为:将字符串str当成有效的表达式来求值并返回计算结果。
BUT!强大的函数有代价。安全性是其最大的缺点。
想象一下,如果我们从文件中读出的不是一个数据结构,而是一句"删除文件"类似的破坏性语句,那么后果实在不堪设设想。
而使用eval就要担这个风险。
所以,我们并不推荐用eval方法来进行反序列化操作(将str转换成python中的数据结构)

序列化的目的

1、以某种存储形式使自定义对象持久化

2、将对象从一个地方传递到另一个地方。

3、使程序更具维护性。

json

Json模块提供了四个功能:dumps、dump、loads、load

loads和dumps

import json
dic = {‘k1‘:‘v1‘,‘k2‘:‘v2‘,‘k3‘:‘v3‘}
str_dic = json.dumps(dic)  #序列化:将一个字典转换成一个字符串
print(type(str_dic),str_dic)  #<class ‘str‘> {"k3": "v3", "k1": "v1", "k2": "v2"}
#注意,json转换完的字符串类型的字典中的字符串是由""表示的

dic2 = json.loads(str_dic)  #反序列化:将一个字符串格式的字典转换成一个字典
#注意,要用json的loads功能处理的字符串类型的字典中的字符串必须由""表示
print(type(dic2),dic2)  #<class ‘dict‘> {‘k1‘: ‘v1‘, ‘k2‘: ‘v2‘, ‘k3‘: ‘v3‘}

list_dic = [1,[‘a‘,‘b‘,‘c‘],3,{‘k1‘:‘v1‘,‘k2‘:‘v2‘}]
str_dic = json.dumps(list_dic) #也可以处理嵌套的数据类型
print(type(str_dic),str_dic) #<class ‘str‘> [1, ["a", "b", "c"], 3, {"k1": "v1", "k2": "v2"}]
list_dic2 = json.loads(str_dic)
print(type(list_dic2),list_dic2) #<class ‘list‘> [1, [‘a‘, ‘b‘, ‘c‘], 3, {‘k1‘: ‘v1‘, ‘k2‘: ‘v2‘}]

load和dump
import json
f = open(‘json_file‘,‘w‘)
dic = {‘k1‘:‘v1‘,‘k2‘:‘v2‘,‘k3‘:‘v3‘}
json.dump(dic,f)  #dump方法接收一个文件句柄,直接将字典转换成json字符串写入文件
f.close()

f = open(‘json_file‘)
dic2 = json.load(f)  #load方法接收一个文件句柄,直接将文件中的json字符串转换成数据结构返回
f.close()
print(type(dic2),dic2)

ensure_ascii关键字参数
import json
f = open(‘file‘,‘w‘)
json.dump({‘国籍‘:‘中国‘},f)
ret = json.dumps({‘国籍‘:‘中国‘})
f.write(ret+‘\n‘)
json.dump({‘国籍‘:‘美国‘},f,ensure_ascii=False)
ret = json.dumps({‘国籍‘:‘美国‘},ensure_ascii=False)
f.write(ret+‘\n‘)
f.close()

pickle

json & pickle 模块

用于序列化的两个模块

  • json,用于字符串 和 python数据类型间进行转换
  • pickle,用于python特有的类型 和 python的数据类型间进行转换

pickle模块提供了四个功能:dumps、dump(序列化,存)、loads(反序列化,读)、load  (不仅可以序列化字典,

列表...可以把python中任意的数据类型序列化

pickle

import pickle
dic = {‘k1‘:‘v1‘,‘k2‘:‘v2‘,‘k3‘:‘v3‘}
str_dic = pickle.dumps(dic)
print(str_dic)  #一串二进制内容

dic2 = pickle.loads(str_dic)
print(dic2)    #字典

import time
struct_time  = time.localtime(1000000000)
print(struct_time)
f = open(‘pickle_file‘,‘wb‘)
pickle.dump(struct_time,f)
f.close()

f = open(‘pickle_file‘,‘rb‘)
struct_time2 = pickle.load(f)
print(struct_time2.tm_year)

这时候机智的你又要说了,既然pickle如此强大,为什么还要学json呢?这里我们要说明一下,json是一种所有的语言都可以识别的数据结构。如果我们将一个字典或者序列化成了一个json存在文件里,那么java代码或者js代码也可以拿来用。但是如果我们用pickle进行序列化,其他语言就不能读懂这是什么了~所以,如果你序列化的内容是列表或者字典,我们非常推荐你使用json模块但如果出于某种原因你不得不序列化其他的数据类型,而未来你还会用python对这个数据进行反序列化的话,那么就可以使用pickle

shelve

shelve也是python提供给我们的序列化工具,比pickle用起来更简单一些。
shelve只提供给我们一个open方法,是用key来访问的,使用起来和字典类似。


shelve
import shelve
f = shelve.open(‘shelve_file‘)
f[‘key‘] = {‘int‘:10, ‘float‘:9.5, ‘string‘:‘Sample data‘}  #直接对文件句柄操作,就可以存入数据
f.close()

import shelve
f1 = shelve.open(‘shelve_file‘)
existing = f1[‘key‘]  #取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错
f1.close()
print(existing)

这个模块有个限制,它不支持多个应用同一时间往同一个DB进行写操作。所以当我们知道我们的应用如果只进行读操作,我们可以让shelve通过只读方式打开DB
shelve只读
import shelve
f = shelve.open(‘shelve_file‘, flag=‘r‘)
existing = f[‘key‘]
f.close()
print(existing)

由于shelve在默认情况下是不会记录待持久化对象的任何修改的,所以我们在shelve.open()时候需要修改默认参数,否则对象的修改不会保存。
设置writeback
import shelve
f1 = shelve.open(‘shelve_file‘)
print(f1[‘key‘])
f1[‘key‘][‘new_value‘] = ‘this was not here before‘
f1.close()

f2 = shelve.open(‘shelve_file‘, writeback=True)
print(f2[‘key‘])
f2[‘key‘][‘new_value‘] = ‘this was not here before‘
f2.close()writeback方式有优点也有缺点。优点是减少了我们出错的概率,并且让对象的持久化对用户更加的透明了;但这种方式并不是所有的情况下都需要,首先,使用writeback以后,shelf在open()的时候会增加额外的内存消耗,并且当DB在close()的时候会将缓存中的每一个对象都写入到DB,这也会带来额外的等待时间。因为shelve没有办法知道缓存中哪些对象修改了,哪些对象没有修改,因此所有的对象都会被写入

re模块

讲正题之前我们先来看一个例子:https://reg.jd.com/reg/person?ReturnUrl=https%3A//www.jd.com/

这是京东的注册页面,打开页面我们就看到这些要求输入个人信息的提示。
假如我们随意的在手机号码这一栏输入一个11111111111,它会提示我们格式有误。
这个功能是怎么实现的呢?
假如现在你用python写一段代码,类似:

phone_number = input(‘please input your phone number : ‘)

你怎么判断这个phone_number是合法的呢?

根据手机号码一共11位并且是只以13、14、15、18开头的数字这些特点,我们用python写了如下代码:
判断手机号码是否合法
while True:
    phone_number = input(‘please input your phone number : ‘)
    if len(phone_number) == 11             and phone_number.isdigit()            and (phone_number.startswith(‘13‘)             or phone_number.startswith(‘14‘)             or phone_number.startswith(‘15‘)             or phone_number.startswith(‘18‘)):
        print(‘是合法的手机号码‘)
    else:
        print(‘不是合法的手机号码‘)
这是你的写法,现在我要展示一下我的写法:
import re
phone_number = input(‘please input your phone number : ‘)
if re.match(‘^(13|14|15|18)[0-9]{9}$‘,phone_number):
        print(‘是合法的手机号码‘)
else:
        print(‘不是合法的手机号码‘)

对比上面的两种写法,此时此刻,我要问你你喜欢哪种方法呀?你肯定还是会说第一种,为什么呢?因为第一种不用学呀!
但是如果现在有一个文件,我让你从整个文件里匹配出所有的手机号码。你用python给我写个试试?
但是学了今天的技能之后,分分钟帮你搞定!

今天我们要学习python里的re模块和正则表达式,学会了这个就可以帮我们解决刚刚的疑问。正则表达式不仅在python领域,在整个编程届都占有举足轻重的地位

不管以后你是不是去做python开发,只要你是一个程序员就应该了解正则表达式的基本使用。如果未来你要在爬虫领域发展,你就更应该好好学习这方面的知识。
但是你要知道,re模块本质上和正则表达式没有一毛钱的关系。re模块和正则表达式的关系 类似于 time模块和时间的关系
你没有学习python之前,也不知道有一个time模块,但是你已经认识时间了 12:30就表示中午十二点半(这个时间可好,一般这会儿就该下课了)。
时间有自己的格式,年月日时分秒,12个月,365天......已经成为了一种规则。你也早就牢记于心了。time模块只不过是python提供给我们的可以方便我们操作时间的一个工具而已

正则表达式本身也和python没有什么关系,就是匹配字符串内容的一种规则

官方定义:正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

正则表达式

一说规则我已经知道你很晕了,现在就让我们先来看一些实际的应用。在线测试工具 http://tool.chinaz.com/regex/

首先你要知道的是,谈到正则,就只和字符串相关了。在我给你提供的工具中,你输入的每一个字都是一个字符串。其次,如果在一个位置的一个值,不会出现什么变化,那么是不需要规则的。  比如你要用"1"去匹配"1",或者用"2"去匹配"2",直接就可以匹配上。这连python的字符串操作都可以轻松做到。那么在之后我们更多要考虑的是在同一个位置上可以出现的字符的范围。
字符组 : [字符组]
在同一个位置可能出现的各种字符组成了一个字符组,在正则表达式中用[]表示
字符分为很多类,比如数字、字母、标点等等。
假如你现在要求一个位置"只能出现一个数字",那么这个位置上的字符只能是0、1、2...9这10个数之一。
正则
待匹配字符
匹配结果
说明
[0123456789]
8
True
在一个字符组里枚举合法的所有字符,字符组里的任意一个字符和"待匹配字符"相同都视为可以匹配
[0123456789]
a
False
由于字符组中没有"a"字符,所以不能匹配
[0-9]
7
True
也可以用-表示范围,[0-9]就和[0123456789]是一个意思
[a-z]
s
True
同样的如果要匹配所有的小写字母,直接用[a-z]就可以表示
[A-Z]
B
True
[A-Z]就表示所有的大写字母
[0-9a-fA-F]
e
True
可以匹配数字,大小写形式的a~f,用来验证十六进制字符

字符:

元字符
匹配内容
匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线
\s 匹配任意的空白符
\d 匹配数字
\n 匹配一个换行符
\t 匹配一个制表符
\b 匹配一个单词的结尾
^ 匹配字符串的开始
$ 匹配字符串的结尾
\W
匹配非字母或数字或下划线
\D
匹配非数字
\S
匹配非空白符
a|b
匹配字符a或字符b
()
匹配括号内的表达式,也表示一个组
[...]
匹配字符组中的字符
[^...]
匹配除了字符组中字符的所有字符

量词:

量词
用法说明
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次

. ^ $

正则 待匹配字符 匹配
结果
说明
海. 海燕海娇海东 海燕海娇海东   匹配所有"海."的字符
^海. 海燕海娇海东 海燕 只从开头匹配"海."
  海.$   海燕海娇海东 海东 只匹配结尾的"海.$"

* + ? { }

正则 待匹配字符 匹配
结果
说明
李.? 李杰和李莲英和李二棍子
李杰
李莲
李二

?表示重复零次或一次,即只匹配"李"后面一个任意字符

李.* 李杰和李莲英和李二棍子 李杰和李莲英和李二棍子
*表示重复零次或多次,即匹配"李"后面0或多个任意字符
李.+ 李杰和李莲英和李二棍子 李杰和李莲英和李二棍子
+表示重复一次或多次,即只匹配"李"后面1个或多个任意字符
李.{1,2} 李杰和李莲英和李二棍子

李杰和
李莲英
李二棍

{1,2}匹配1到2次任意字符

注意:前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配

正则 待匹配字符 匹配
结果
说明
李.*? 李杰和李莲英和李二棍子

惰性匹配

字符集[][^]

正则 待匹配字符 匹配
结果
说明
李[杰莲英二棍子]* 李杰和李莲英和李二棍子
李杰
李莲英
李二棍子

表示匹配"李"字后面[杰莲英二棍子]的字符任意次

李[^和]* 李杰和李莲英和李二棍子

李杰
李莲英
李二棍子

表示匹配一个不是"和"的字符任意次
[\d] 456bdha3
4
5
6
3

表示匹配任意一个数字,匹配到4个结果
[\d]+ 456bdha3
456
3

表示匹配任意个数字,匹配到2个结果

分组 ()与 或 |[^]

身份证号码是一个长度为15或18个字符的字符串,如果是15位则全部???数字组成,首位不能为0;如果是18位,则前17位全部是数字,末位可能是数字或x,下面我们尝试用正则来表示:

正则 待匹配字符 匹配
结果
说明
^[1-9]\d{13,16}[0-9x]$ 110101198001017032
110101198001017032

   表示可以匹配一个正确的身份证号
^[1-9]\d{13,16}[0-9x]$ 1101011980010170
1101011980010170

表示也可以匹配这串数字,但这并不是一个正确的身份证号码,它是一个16位的数字
^[1-9]\d{14}(\d{2}[0-9x])?$ 1101011980010170
False

现在不会匹配错误的身份证号了()表示分组,将\d{2}[0-9x]分成一组,就可以整体约束他们出现的次数为0-1次
^([1-9]\d{16}[0-9x]|[1-9]\d{14})$ 110105199812067023
110105199812067023

表示先匹配[1-9]\d{16}[0-9x]如果没有匹配上就匹配[1-9]\d{14}

转义符 \

在正则表达式中,有很多有特殊意义的是元字符,比如\d和\s等,如果要在正则中匹配正常的"\d"而不是"数字"就需要对"\"进行转义,变成‘\\‘。

在python中,无论是正则表达式,还是待匹配的内容,都是以字符串的形式出现的,在字符串中\也有特殊的含义,本身还需要转义。所以如果匹配一次"\d",字符串中要写成‘\\d‘,那么正则里就要写成"\\\\d",这样就太麻烦了。这个时候我们就用到了r‘\d‘这个概念,此时的正则是r‘\\d‘就可以了。

正则 待匹配字符 匹配
结果
说明
\d \d  False
因为在正则表达式中\是有特殊意义的字符,所以要匹配\d本身,用表达式\d无法匹配
\\d \d  True
转义\之后变成\\,即可匹配
"\\\\d" ‘\\d‘  True
如果在python中,字符串中的‘\‘也需要转义,所以每一个字符串‘\‘又需要转义一次
r‘\\d‘ r‘\d‘  True
在字符串之前加r,让整个字符串不转义

贪婪匹配

贪婪匹配:在满足匹配时,匹配尽可能长的字符串,默认情况下,采用贪婪匹配

正则 待匹配字符 匹配
结果
说明
<.*>
<script>...<script>

<script>...<script>
默认为贪婪匹配模式,会匹配尽量长的字符串
<.*?> r‘\d‘

<script>
<script>

加上?为将贪婪匹配模式转为非贪婪匹配模式,会匹配尽量短的字符串
几个常用的非贪婪匹配Pattern
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复
.*?的用法

. 是任意字符
* 是取 0 至 无限长度
? 是非贪婪模式。
何在一起就是 取尽量少的任意字符,一般不会这么单独写,他大多用在:
.*?x

就是取前面任意长度的字符,直到一个x出现

re模块下的常用方法

import re

ret = re.findall(‘a‘, ‘eva egon yuan‘)  # 返回所有满足匹配条件的结果,放在列表里
print(ret) #结果 : [‘a‘, ‘a‘]

ret = re.search(‘a‘, ‘eva egon yuan‘).group()
print(ret) #结果 : ‘a‘
# 函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以
# 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。

ret = re.match(‘a‘, ‘abc‘).group()  # 同search,不过尽在字符串开始处进行匹配
print(ret)
#结果 : ‘a‘

ret = re.split(‘[ab]‘, ‘abcd‘)  # 先按‘a‘分割得到‘‘和‘bcd‘,在对‘‘和‘bcd‘分别按‘b‘分割
print(ret)  # [‘‘, ‘‘, ‘cd‘]

ret = re.sub(‘\d‘, ‘H‘, ‘eva3egon4yuan4‘, 1)#将数字替换成‘H‘,参数1表示只替换1个
print(ret) #evaHegon4yuan4

ret = re.subn(‘\d‘, ‘H‘, ‘eva3egon4yuan4‘)#将数字替换成‘H‘,返回元组(替换的结果,替换了多少次)
print(ret)

obj = re.compile(‘\d{3}‘)  #将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字
ret = obj.search(‘abc123eeee‘) #正则表达式对象调用search,参数为待匹配的字符串
print(ret.group())  #结果 : 123

import re
ret = re.finditer(‘\d‘, ‘ds3sy4784a‘)   #finditer返回一个存放匹配结果的迭代器
print(ret)  # <callable_iterator object at 0x10195f940>
print(next(ret).group())  #查看第一个结果
print(next(ret).group())  #查看第二个结果
print([i.group() for i in ret])  #查看剩余的左右结果

注意:

1 findall的优先级查询:

import re

ret = re.findall(‘www.(baidu|oldboy).com‘, ‘www.oldboy.com‘)
print(ret)  # [‘oldboy‘]     这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可

ret = re.findall(‘www.(?:baidu|oldboy).com‘, ‘www.oldboy.com‘)
print(ret)  # [‘www.oldboy.com‘]

2 split的优先级查询

ret=re.split("\d+","eva3egon4yuan")
print(ret) #结果 : [‘eva‘, ‘egon‘, ‘yuan‘]

ret=re.split("(\d+)","eva3egon4yuan")
print(ret) #结果 : [‘eva‘, ‘3‘, ‘egon‘, ‘4‘, ‘yuan‘]

#在匹配部分加上()之后所切出的结果是不同的,
#没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项,
#这个在某些需要保留匹配部分的使用过程是非常重要的。

import json
dic = {‘k1‘:‘v1‘,‘k2‘:‘v2‘,‘k3‘:‘v3‘}
str_dic = json.dumps(dic)  #序列化:将一个字典转换成一个字符串
print(type(str_dic),str_dic)  #<class ‘str‘> {"k3": "v3", "k1": "v1", "k2": "v2"}
#注意,json转换完的字符串类型的字典中的字符串是由""表示的

dic2 = json.loads(str_dic)  #反序列化:将一个字符串格式的字典转换成一个字典
#注意,要用json的loads功能处理的字符串类型的字典中的字符串必须由""表示
print(type(dic2),dic2)  #<class ‘dict‘> {‘k1‘: ‘v1‘, ‘k2‘: ‘v2‘, ‘k3‘: ‘v3‘}

list_dic = [1,[‘a‘,‘b‘,‘c‘],3,{‘k1‘:‘v1‘,‘k2‘:‘v2‘}]
str_dic = json.dumps(list_dic) #也可以处理嵌套的数据类型
print(type(str_dic),str_dic) #<class ‘str‘> [1, ["a", "b", "c"], 3, {"k1": "v1", "k2": "v2"}]
list_dic2 = json.loads(str_dic)
print(type(list_dic2),list_dic2) #<class ‘list‘> [1, [‘a‘, ‘b‘, ‘c‘], 3, {‘k1‘: ‘v1‘, ‘k2‘: ‘v2‘}]

时间: 2024-11-08 09:14:36

部分模块的相关文章

Day5 - 常用模块学习

本节大纲: 模块介绍(模块导入方法) time &datetime模块 random os sys shutil json & picle shelve xml处理 yaml处理 configparser hashlib subprocess logging模块 re正则表达式 模块,用一堆代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需要多个函数才能完成(函数又

c# 无法加载xxx.dll 找不到指定的模块(如何指定文件夹)

如果直接放在项目运行目录,例如bin/debug可以直接加载,但是这样比较乱. 如果在放debug里面的一个文件夹里面,有可能会报错“无法加载xxx.dll 找不到指定的模块”. 如果路径写成这样就会报错 framework/linphone 解决方法:将/ 改成"\" framework\linphone

LEDAPS1.3.0版本移植到windows平台----HuCsm云掩膜模块

这个是2012年左右放在百度空间的,谁知百度空间关闭...转移到博客园. 最近项目用到3.1.2版本的LEDAPS,新版本的使用情况会在后续文章中慢慢丰富. HuCsm是将LEDAPS项目中的TM/ETM+大气校正流程系列算法中的云掩膜模块由linux系统移植到windows下的产物,代码本身改动不大,使用接口不变. 包含文件: HuCsm.exe hd423m.dll hm423m.dll 编译程序需要包含的静态库有: gctp.lib hdfeos.lib hd423m.lib hm423m

Python学习系列----第五章 模块

5.1 如何引入模块 在Python中用关键字import来引入某个模块,比如要引用模块math,就可以在文件最开始的地方用import math来引入.在调用math模块中的函数时,必须这样引用: 模块名.函数名 有时候我们只需要用到模块中的某个函数,只需要引入该函数即可,此时可以通过语句 from 模块名 import 函数名1,函数名2.... 5.2 如何定义自己的模块 在Python中,每个Python文件都可以作为一个模块,模块的名字就是文件的名字. 比如有这样一个文件test.py

Python:hashlib加密模块,flask模块写登录接口

hashlib模块 主要用于加密相关的操作,(比如说加密字符串)在python3的版本里,代替了md5和sha模块,主要提供 sha1, sha224, sha256, sha384, sha512 ,md5 这些加密方式 import  hashlib m = hashlib.md5()   #用md5加密的方式(md5加密后无法解密),创建一个md5的对象 m.update(b"Hello")  #b代表二进制字节bytes,把字符串hello转成字节,然后加密:用b给一个变量转换

python如何使用pymysql模块

Python 3.x 操作MySQL的pymysql模块详解 前言pymysql是Python中操作MySQL的模块,其使用方法和MySQLdb几乎相同.但目前pymysql支持python3.x而MySQLdb不支持3.x版本. 一.安装 pip3 install pymysql 二.pymysql方法 pymysql.connect()参数说明 参数 类型 说明 host str mysql服务器地址 port int mysql服务器端口号 user str 用户名 passwd str

微控工具xp模块-开发版[微信(wechat)二次开发模块]

http://repo.xposed.info/module/com.easy.wtool 微控工具xp模块-开发版[微信(wechat)二次开发模块] 基于xposed框架的微信二次开发模块,方便开发者用微信做一些扩展功能(如微信群发.多群直播等...) 目前支持功能: 发文本消息 发图片消息 发语音消息 发视频消息 获取微信好友列表 群列表 支持群发消息 支持消息转发(目前支持文本.图片.语音.视频.图文消息转发) 群管理功能(建群.加人.踢人.设置公告.改群名.退群.解散群) [注:本模块

用ESP8266 WIFI模块连接服务器,并实现与服务器相互通讯

最近在做一个智能锁的项目,该项目要求实现在任何地方(当然是要有网络的)可以在手机上用APP开锁.而我负责的部分主要是实现底层与服务器连接,并且要能相互通讯.考虑了很多问题,最终选择了用ESP8266 WIFI模块实现了这个功能.下面向大家就简单分享一下. 工具:网络调试助手  ESP8266  STM32F1开发板 首先,用网络调试助手来虚拟一个服务器,如下: 有了服务器后,接下来我们就要用WIFI来连接这个服务器.ESP8266 有三种工作模式,由于项目要求,我选用了STA中的客户端模式.下面

Saltstack批量编译部署nginx(多模块)

最近一直在研究saltstack的同步文件和批量执行命令,随着架构的变大,批量部署的需求也变得明显起来了,我需要用一条命令就部署好nginx和tomcat,并且符合我所有的环境需求,可以直接投入生产环境使用,这就需要用到saltstack的批量安装部署功能了.这篇文章主要介绍nginx的批量部署,下篇讲解tomcat多实例的批量部署方法. 环境介绍: Centos 6.5 salt 2015.5.10 nginx 1.12.0 minion:test 1.修改master配置文件,修改后重启服务

python:模块导入之浅认识

(1)python有大量的模块: 1.内部提供的模块:不需要安装,可以直接调用 2.第三方库:包括业内开源的模块和自己开发的,需要安装 (2)什么是pyc文件: pyc文件的pycodeobject的一种持久化保存,而pycodeobject则是python真正编译的结果 明白什么时pyc文件,则我们需要从python的运行过程说起: 1.首先当python程序运行时,编译的结果则是保存在位于内存中的pycodeobject中,当python运行结束时,将pycodeobject写入到pyc文件