内置模块
Posted ycmyay
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内置模块相关的知识,希望对你有一定的参考价值。
认识模块
什么是模块?
常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。
但其实import加载的模块分为四个通用类别:
1 使用python编写的代码(.py文件)
2 已被编译为共享库或DLL的C或C++扩展
3 包好一组模块的包
4 使用C编写并链接到python解释器的内置模块
为何要使用模块?
如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script。
随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用,
常用模块
collections模块
在内置数据类型(dict、list、set、tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter、deque、defaultdict、namedtuple和OrderedDict等。
1.namedtuple: 生成可以使用名字来访问元素内容的tuple
2.deque: 双端队列,可以快速的从另外一侧追加和推出对象
3.Counter: 计数器,主要用来计数
4.OrderedDict: 有序字典
5.defaultdict: 带有默认值的字典
namedtuple
我们知道tuple
可以表示不变集合,例如,一个点的二维坐标就可以表示成:
>>> p = (1, 2)
但是,看到(1, 2),很难看出这个tuple是用来表示一个坐标的。
这时,namedtuple
就派上了用场:
>>> from collections import namedtuple
>>> Point = namedtuple(\'Point\', [\'x\', \'y\'])
>>> p = Point(1, 2)
>>> p.x
1
>>> p.y
2
类似的,如果要用坐标和半径表示一个圆,也可以用namedtuple
定义:
#namedtuple(\'名称\', [属性list]):
Circle = namedtuple(\'Circle\', [\'x\', \'y\', \'r\'])
deque
使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。
deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:
>>> from collections import deque
>>> q = deque([\'a\', \'b\', \'c\'])
>>> q.append(\'x\')
>>> q.appendleft(\'y\')
>>> q
deque([\'y\', \'a\', \'b\', \'c\', \'x\'])
deque除了实现list的append()
和pop()
外,还支持appendleft()
和popleft()
,这样就可以非常高效地往头部添加或删除元素。
OrderedDict
使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。
如果要保持Key的顺序,可以用OrderedDict
:
>>> from collections import OrderedDict
>>> d = dict([(\'a\', 1), (\'b\', 2), (\'c\', 3)])
>>> d # dict的Key是无序的
\'a\': 1, \'c\': 3, \'b\': 2
>>> od = OrderedDict([(\'a\', 1), (\'b\', 2), (\'c\', 3)])
>>> od # OrderedDict的Key是有序的
OrderedDict([(\'a\', 1), (\'b\', 2), (\'c\', 3)])
注意,OrderedDict
的Key会按照插入的顺序排列,不是Key本身排序:
>>> od = OrderedDict()
>>> od[\'z\'] = 1
>>> od[\'y\'] = 2
>>> od[\'x\'] = 3
>>> od.keys() # 按照插入的Key的顺序返回
[\'z\', \'y\', \'x\']
defaultdict
有如下值集合 [11,22,33,44,55,66,77,88,99,90...],将所有大于66的值保存至字典的第一个key中,将小于66的值保存至第二个key的值中。
即: \'k1\': 大于66,\'k2\': 小于66
values = [11, 22, 33,44,55,66,77,88,99,90]
my_dict =
for value in values:
if value>66:
if my_dict.has_key(\'k1\'):
my_dict[\'k1\'].append(value)
else:
my_dict[\'k1\'] = [value]
else:
if my_dict.has_key(\'k2\'):
my_dict[\'k2\'].append(value)
else:
my_dict[\'k2\'] = [value]
from collections import defaultdict
values = [11, 22, 33,44,55,66,77,88,99,90]
my_dict = defaultdict(list)
for value in values:
if value>66:
my_dict[\'k1\'].append(value)
else:
my_dict[\'k2\'].append(value)
使用dict
时,如果引用的Key不存在,就会抛出KeyError
。如果希望key不存在时,返回一个默认值,就可以用defaultdict
:
>>> from collections import defaultdict
>>> dd = defaultdict(lambda: \'N/A\')
>>> dd[\'key1\'] = \'abc\'
>>> dd[\'key1\'] # key1存在
\'abc\'
>>> dd[\'key2\'] # key2不存在,返回默认值
\'N/A\'
Counter
Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的Interger(包括0和负数)。Counter类和其他语言的bags或multisets很相似。
c = Counter(\'abcdeabcdabcaba\')
print c
输出:Counter(\'a\': 5, \'b\': 4, \'c\': 3, \'d\': 2, \'e\': 1)
其他详细内容 http://www.cnblogs.com/Eva-J/articles/7291842.html
时间模块
和时间有关系的我们就要用到时间模块。在使用模块之前,应该首先导入这个模块。
#常用方法
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’
%y 两位数的年份表示(00-99)
%Y 四位数的年份表示(000-9999)
%m 月份(01-12)
%d 月内中的一天(0-31)
%H 24小时制小时数(0-23)
%I 12小时制小时数(01-12)
%M 分钟数(00=59)
%S 秒(00-59)
%a 本地简化星期名称
%A 本地完整星期名称
%b 本地简化的月份名称
%B 本地完整的月份名称
%c 本地相应的日期表示和时间表示
%j 年内的一天(001-366)
%p 本地A.M.或P.M.的等价符
%U 一年中的星期数(00-53)星期天为星期的开始
%w 星期(0-6),星期天为星期的开始
%W 一年中的星期数(00-53)星期一为星期的开始
%x 本地相应的日期表示
%X 本地相应的时间表示
%Z 当前时区的名称
%% %号本身
(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\'
#时间元组: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时间,与英国伦敦当地时间一致
#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)
>>>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 %b %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))
datetime模块
1.datetime.now() # 获取当前datetime
datetime.utcnow() # 获取当前格林威治时间
from datetime import datetime
#获取当前本地时间
a=datetime.now()
print(\'当前日期:\',a)
#获取当前世界时间
b=datetime.utcnow()
print(\'世界时间:\',b)
2.datetime(2017, 5, 23, 12, 20) # 用指定日期时间创建datetime
from datetime import datetime
#用指定日期创建
c=datetime(2017, 5, 23, 12, 20)
print(\'指定日期:\',c)
3.将以下字符串转换成datetime类型:
\'2017/9/30\'
\'2017年9月30日星期六\'
\'2017年9月30日星期六8时42分24秒\'
\'9/30/2017\'
\'9/30/2017 8:42:50 \'
from datetime import datetime
d=datetime.strptime(\'2017/9/30\',\'%Y/%m/%d\')
print(d)
e=datetime.strptime(\'2017年9月30日星期六\',\'%Y年%m月%d日星期六\')
print(e)
f=datetime.strptime(\'2017年9月30日星期六8时42分24秒\',\'%Y年%m月%d日星期六%H时%M分%S秒\')
print(f)
g=datetime.strptime(\'9/30/2017\',\'%m/%d/%Y\')
print(g)
h=datetime.strptime(\'9/30/2017 8:42:50 \',\'%m/%d/%Y %H:%M:%S \')
print(h)
4.将以下datetime类型转换成字符串:
2017年9月28日星期4,10时3分43秒
Saturday, September 30, 2017
9/30/2017 9:22:17 AM
September 30, 2017
# 时间字符串格式化
from datetime import datetime
i=datetime(2017,9,28,10,3,43)
print(i.strftime(\'%Y年%m月%d日%A,%H时%M分%S秒\'))
j=datetime(2017,9,30,10,3,43)
print(j.strftime(\'%A,%B %d,%Y\'))
k=datetime(2017,9,30,9,22,17)
print(k.strftime(\'%m/%d/%Y %I:%M:%S%p\'))
l=datetime(2017,9,30)
print(l.strftime(\'%B %d,%Y\'))
5.用系统时间输出以下字符串:
今天是2017年9月30日
今天是这周的第?天
今天是今年的第?天
今周是今年的第?周
今天是当月的第?天
from datetime import datetime
#获取当前系统时间
m=datetime.now()
print(m.strftime(\'今天是%Y年%m月%d日\'))
print(m.strftime(\'今天是这周的第%w天\'))
print(m.strftime(\'今天是今年的第%j天\'))
print(m.strftime(\'今周是今年的第%W周\'))
print(m.strftime(\'今天是当月的第%d天\'))
random模块
>>> import random
#随机小数
>>> random.random() # 大于0且小于1之间的小数
0.7664338663654585
>>> random.uniform(1,3) #大于1小于3的小数
1.6270147180533838#恒富:发红包
#随机整数
>>> random.randint(1,5) # 大于等于1且小于等于5之间的整数
>>> random.randrange(1,10,2) # 大于等于1且小于10之间的奇数
#随机选择一个返回
>>> random.choice([1,\'23\',[4,5]]) # #1或者23或者[4,5]
#随机选择多个返回,返回的个数为函数的第二个参数
>>> random.sample([1,\'23\',[4,5]],2) # #列表元素任意2个组合
[[4, 5], \'23\']
#打乱列表顺序
>>> item=[1,3,5,7,9]
>>> random.shuffle(item) # 打乱次序
>>> item
[5, 1, 3, 7, 9]
>>> random.shuffle(item)
>>> item
[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.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.system("bash command") 运行shell命令,直接显示
os.popen("bash command).read() 运行shell命令,获取执行结果
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd
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)是创建时间(详细信息参见平台的文档)。
os.sep 输出操作系统特定的路径分隔符,win下为"\\\\",Linux下为"/"
os.linesep 输出当前平台使用的行终止符,win下为"\\r\\n",Linux下为"\\n"
os.pathsep 输出用于分割文件路径的字符串 win下为;,Linux下为:
os.name 输出字符串指示当前使用平台。win->\'nt\'; Linux->\'posix\'
sys模块
sys模块是与python解释器交互的一个接口
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()
# 其他参数说明
Serialize obj to a JSON formatted str.(字符串表示的json对象)
Skipkeys:默认值是False,如果dict的keys内的数据不是python的基本类型(str,unicode,int,long,float,bool,None),设置为False时,就会报TypeError的错误。此时设置成True,则会跳过这类key
ensure_ascii:,当它为True的时候,所有非ASCII码字符显示为\\uXXXX序列,只需在dump时将ensure_ascii设置为False即可,此时存入json的中文即可正常显示。)
If check_circular is false, then the circular reference check for container types will be skipped and a circular reference will result in an OverflowError (or worse).
If allow_nan is false, then it will be a ValueError to serialize out of range float values (nan, inf, -inf) in strict compliance of the JSON specification, instead of using the JavaScript equivalents (NaN, Infinity, -Infinity).
indent:应该是一个非负的整型,如果是0就是顶格分行显示,如果为空就是一行最紧凑显示,否则会换行且按照indent的数值显示前面的空白分行显示,这样打印出来的json数据也叫pretty-printed json
separators:分隔符,实际上是(item_separator, dict_separator)的一个元组,默认的就是(‘,’,’:’);这表示dictionary内keys之间用“,”隔开,而KEY和value之间用“:”隔开。
default(obj) is a function that should return a serializable version of obj or raise TypeError. The default simply raises TypeError.
sort_keys:将数据根据keys的值进行排序。
To use a custom JSONEncoder subclass (e.g. one that overrides the .default() method to serialize additional types), specify it with the cls kwarg; otherwise JSONEncoder is used.
# json的格式化输出
import json
data = \'username\':[\'李华\',\'二愣子\'],\'sex\':\'male\',\'age\':16
json_dic2 = json.dumps(data,sort_keys=True,indent=2,separators=(\',\',\':\'),ensure_ascii=False)
print(json_dic2)
pickle
json & pickle 模块
用于序列化的两个模块
- json,用于字符串 和 python数据类型间进行转换
- pickle,用于python特有的类型 和 python的数据类型间进行转换
pickle模块提供了四个功能:dumps、dump(序列化,存)、loads(反序列化,读)、load (不仅可以序列化字典,列表...可以把python中任意的数据类型序列化)
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
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到m次 |
. ^ $
正则 | 待匹配字符 | 匹配 结果 | 说明 |
---|---|---|---|
海. | 海燕海娇海东 | 海燕海娇海东 | 匹配所有"海."的字符 |
^海. | 海燕海娇海东 | 海燕 | 只从开头匹配"海." |
海.$ | 海燕海娇海东 | 海东 | 只匹配结尾的"海.$" |
* + ?
正则 | 待匹配字符 | 匹配 结果 | 说明 |
---|---|---|---|
李.? | 李杰和李莲英和李二棍子 | 李杰 李莲 李二 | ?表示重复零次或一次,即只匹配"李"后面一个任意字符 |
李.* | 李杰和李莲英和李二棍子 | 李杰和李莲英和李二棍子 | *表示重复零次或多次,即匹配"李"后面0或多个任意字符 |
李.+ | 李杰和李莲英和李二棍子 | 李杰和李莲英和李二棍子 | +表示重复一次或多次,即只匹配"李"后面1个或多个任意字符 |
李. | 李杰和李莲英和李二棍子 | 李杰和 李莲英 李二棍 | 1,2匹配1到2次任意字符 |
注意:前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配
正则 | 待匹配字符 | 匹配 结果 | 说明 |
---|---|---|---|
李.*? | 李杰和李莲英和李二棍子 | 李 李 李 | 惰性匹配 |
字符集[][^]
正则 | 待匹配字符 | 匹配 结果 | 说明 |
---|---|---|---|
李[杰莲英二棍子]* | 李杰和李莲英和李二棍子 | 李杰 李莲英 李二棍子 | 表示匹配"李"字后面[杰莲英二棍子]的字符任意次 |
李[^和]* | 李杰和李莲英和李二棍子 | 李杰 李莲英 李二棍子 | 表示匹配一个不是"和"的字符任意次 |
[\\d] | 456bdha3 | 4 5 6 3 | 表示匹配任意一个数字,匹配到4个结果 |
[\\d]+ | 456bdha3 | 456 3 | 表示匹配任意个数字,匹配到2个结果 |
分组 ()与 或 |[^]
身份证号码是一个长度为15或18个字符的字符串,如果是15位则全部有数字组成,首位不能为0;如果是18位,则前17位全部是数字,末位可能是数字或x,下面我们尝试用正则来表示:
正则 | 待匹配字符 | 匹配 结果 | 说明 |
---|---|---|---|
[1]\\d13,16[0-9x]$ | 110101198001017032 | 110101198001017032 | 表示可以匹配一个正确的身份证号 |
[2]\\d13,16[0-9x]$ | 1101011980010170 | 1101011980010170 | 表示也可以匹配这串数字,但这并不是一个正确的身份证号码,它是一个16位的数字 |
[3]\\d14(\\d2[0-9x])?$ | 1101011980010170 | False | 现在不会匹配错误的身份证号了()表示分组,将\\d2[0-9x]分成一组,就可以整体约束他们出现的次数为0-1次 |
^([1-9]\\d16[0-9x]|[1-9]\\d14)$ | 110105199812067023 | 110105199812067023 | 表示先匹配[1-9]\\d16[0-9x]如果没有匹配上就匹配[1-9]\\d14 |
转义符 \\
在正则表达式中,有很多有特殊意义的是元字符,比如\\n和\\s等,如果要在正则中匹配正常的"\\n"而不是"换行符"就需要对""进行转义,变成\'\\\'。
在python中,无论是正则表达式,还是待匹配的内容,都是以字符串的形式出现的,在字符串中\\也有特殊的含义,本身还需要转义。所以如果匹配一次"\\n",字符串中要写成\'\\n\',那么正则里就要写成"\\\\n",这样就太麻烦了。这个时候我们就用到了r\'\\n\'这个概念,此时的正则是r\'\\n\'就可以了。
正则 | 待匹配字符 | 匹配 结果 | 说明 |
---|---|---|---|
\\n | \\n | False | 因为在正则表达式中\\是有特殊意义的字符,所以要匹配\\n本身,用表达式\\n无法匹配 |
\\n | \\n | True | 转义\\之后变成\\\\,即可匹配 |
"\\\\n" | \'\\n\' | True | 如果在python中,字符串中的\'\\\'也需要转义,所以每一个字符串\'\\\'又需要转义一次 |
r\'\\n\' | r\'\\n\' | True | 在字符串之前加r,让整个字符串不转义 |
贪婪匹配
贪婪匹配:在满足匹配时,匹配尽可能长的字符串,默认情况下,采用贪婪匹配
正则 | 待匹配字符 | 匹配 结果 | 说明 |
---|---|---|---|
<.*> |
python内置模块
python内置模块[sys,os,os.path,stat]
内置模块是python自带功能,在使用内置模块时,需要遵循 先导入在 使用
一、sys
对象 | 描述 |
sys.argv | 命令行参数获取,返回类型为列表,第一个元素为程序的本身的路径 |
sys.path | 返回模块的搜索路径列表,第一个元素为当前程序所在目录;初始化时使用PYTHONPATH环境变量的值 |
sys.modules.keys() | 返回所有已经导入的模块列表 |
sys.modules | 返回所有已经导入的模块字典,key模块名,value是模块路径 |
sys.exc_info() | 获取当前正在处理的异常类,exc_type,exc_value,exc_traceback当前处理的异常详细信息 |
sys.exc_clear() | 用来清除当前线程所出现的当前的或最近的错误信息 |
sys.exec_prefix | 返回python文件安装的位置 |
sys.exit(n) | 退出程序,正常退出时exit(0) |
sys.hexversion | 获取python解释程序的版本值,16进制格式如:0x020103F0 |
sys.version | 获取python解释程序的版本信息 |
sys.displayhook(value) | 如果value非空,这个函数会把他输出到sys.stdout(详细使用参考文档) |
sys.excepthook | 异常回溯相关 |
sys.stdin | 标准输入 |
sys.stdin.read() | 输入一行 |
sys.stdin.readline() | 从标准输入读一行,sys.stdout.write("a") 屏幕输出a |
sys.stdout | 标准输出 |
sys.stdout.write(‘aaa’) | 标准输出内容 |
sys.stdout.writelines() | 无换行输出 |
sys.stderr | 错误相关 |
sys.pathform | 返回操作系统平台名称 |
sys.byteorder | 本地字节规则的指示器,big-endian平台的值是’big’,little-endian平台的值是’little’ |
sys.copyright | 记录python版权相关的东西 |
sys.api_version | 解释器的C的API版本 |
sys.version_info | ‘final‘表示最终,也有‘candidate‘表示候选,表示版本级别,是否有后继的发行 |
sys.getdefaultencoding() | 返回当前你所用的默认的字符编码格式 |
sys.getfilesystemencoding() | 返回将Unicode文件名转换成系统文件名的编码的名字 |
sys.builtin_module_names | Python解释器导入的内建模块列表 |
sys.executable | Python解释程序路径 |
sys.getwindowsversion() | 获取Windows的版本 |
二、os模块
对象 | 描述 |
os.remove() | 删除文件 |
os.unlink() | 删除文件 |
os.rename() | 重命名文件 |
os.listdir() | 列出指定目录下所有文件 |
os.curdir | 返回当前目录: ( ‘.‘ ) |
os.pardir | 获取当前目录的父目录字符串名:( ‘..‘ ) |
os.chdir() | 改变当前工作目录 |
os.getcwd() | 获取当前文件路径 |
os.mkdir() | 新建目录 |
os.rmdir() | 删除空目录(删除非空目录, 使用shutil.rmtree()) |
os.makedirs() | 创建多级目录 |
os.removedirs() | 删除多级目录 |
os.stat(file) | 获取文件属性 |
os.chmod(file) | 修改文件权限 |
os.utime(file) | 修改文件时间戳 |
os.name | 获取操作系统标识,字符串指示当前使用平台。win - > ‘nt‘ ; Linux - > ‘posix‘ |
os.sep | 操作系统特定的路径分隔符,win下为 "\\",Linux下为" / " |
os.linesep | 当前平台使用的行终止符,win下为 "\r\n" ,Linux下为 "\n" |
os.pathsep | 用于分割文件路径的字符串 |
os.environ | 获取系统环境变量 |
os.system() | 执行操作系统命令 |
os.execvp() | 启动一个新进程 |
os.access(path, mode) | 判断文件权限 |
os.wait() | 等待任何一个子进程结束,返回一个tuple,包括子进程的进程ID和退出状态信息 |
三、os.path模块
os.path.getctime()返回文件创返回文件大小 字节单位建时间 浮点型os.path.getsize()
对象 | 描述 |
os.path.split(filename) | 将文件路径和文件名分割(会将最后一个目录作为文件名而分离) |
os.path.splitext(filename) | 将文件路径和文件扩展名分割成一个元组 |
os.path.dirname(filename) | 返回文件路径的目录部分 |
os.path.basename(filename) | 返回文件路径的文件名部分 |
os.path.join(dirname,basename) | 将文件路径和文件名凑成完整文件路径 |
os.path.abspath(name) | 获得绝对路径 |
os.path.splitunc(path) | 把路径分割为挂载点和文件名 |
os.path.normpath(path) | 规范path字符串形式 |
os.path.exists() | 判断文件或目录是否存在 |
os.path.isabs() | 如果path是绝对路径,返回True |
os.path.realpath(path) | 返回path的真实路径 |
os.path.relpath(path[, start]) | 从start开始计算相对路径 |
os.path.normcase(path) | 转换path的大小写和斜杠 |
os.path.isdir(name) | 判断name是不是一个目录,name不是目录就返回false |
os.path.isfile(name) | 判断name是不是一个文件,不存在返回false |
os.path.islink() | 判断文件是否连接文件,返回boolean |
os.path.ismount() | 指定路径是否存在且为一个挂载点,返回boolean |
os.path.samefile() | 是否相同路径的文件,返回boolean |
os.path.getatime() | 返回最近访问时间 浮点型 |
os.path.getmtime() | 返回上一次修改时间 浮点型 |
os.path.getctime() | 返回文件创建时间 浮点型 |
os.path.getsize() | 返回文件大小 字节单位 |
os.path.commonprefix(list) | 返回list(多个路径)中,所有path共有的最长的路径 |
os.path.lexists | 路径存在则返回True,路径损坏也返回True |
os.path.expanduser(path) | 把path中包含的"~"和"~user"转换成用户目录 |
os.path.expandvars(path) | 根据环境变量的值替换path中包含的”$name”和”${name}” |
os.path.sameopenfile(fp1, fp2) | 判断fp1和fp2是否指向同一文件 |
os.path.samestat(stat1, stat2) | 判断stat tuple stat1和stat2是否指向同一个文件 |
os.path.splitdrive(path) | 一般用在windows下,返回驱动器名和路径组成的元组 |
os.path.walk(path, visit, arg) | 遍历path,给每个path执行一个函数详细见手册 |
os.path.supports_unicode_filenames | 设置是否支持unicode路径名 |
四、stat模块:描述os.stat()返回的文件属性列表中各值的意义
对象 | 描述 |
fileStats = os.stat(path) | 获取到的文件属性列表 |
fileStats[stat.ST_MODE] | 获取文件的模式 |
fileStats[stat.ST_SIZE] | 文件大小 |
fileStats[stat.ST_MTIME] | 文件最后修改时间 |
fileStats[stat.ST_ATIME] | 文件最后访问时间 |
fileStats[stat.ST_CTIME] | 文件创建时间 |
stat.S_ISDIR(fileStats[stat.ST_MODE]) | 是否目录 |
stat.S_ISREG(fileStats[stat.ST_MODE]) | 是否一般文件 |
stat.S_ISLNK(fileStats[stat.ST_MODE]) | 是否连接文件 |
stat.S_ISSOCK(fileStats[stat.ST_MODE]) | 是否COCK文件 |
stat.S_ISFIFO(fileStats[stat.ST_MODE]) | 是否命名管道 |
stat.S_ISBLK(fileStats[stat.ST_MODE]) | 是否块设备 |
stat.S_ISCHR(fileStats[stat.ST_MODE]) | 是否字符设置 |
以上是关于内置模块的主要内容,如果未能解决你的问题,请参考以下文章