5.1 存储
1.文件
为了长期持续地存储,python必须把数据存储在磁盘中,这样,即使断电或者程序结束,数据依然存在。
在python中可以通过内置函数open来船舰文件对象,在调用时需要说明文件名以及打开方式:
创建一个新记事本对象:
f = open('Neo','w')
此时在默认目录下新建了一个‘Neo.txt’文档。在文档中先输入自定义语句Vinasis_Ra_Alwar
对文件‘Neo.txt’进行操作,其中read(10)为读取10哥字节的数据,readline()为读取一行,readlines()为读取所有行。
另外,文件的打开方式也有不同,以‘w’或‘a’方式打开表示我么可以写入文本:
若要写入一行,则需要在字符串末尾处加上换行符:Windows系统下为‘\r\n’,Unix系统下为‘\n’。
在读写完毕后,应该及时关闭文件,以免造成错误:
2.上下文管理器
上下文管理器(context manager)用于规定某个对象的使用范围。上下文管理器可以在不需要文件的时候自动关闭文件。
※有语法:with...as...
这里用了with...as...结构,上下文管理器有隶属于它的程序快,当隶属它的程序块结束时,也就是上下语句不再缩进时,上下文管理器就会自动关闭文件。
调用n.closed来验证文件是否关闭。输出为True,即文件已经关闭。
通过上下文管理器,我们相当于用缩进来表达文件的打开范围。
使用上下文管理器语法时,python会在进入程序块之前自动调用文件对象的__enter__()方法,在结束程序块时调用文件对象的__exit__()方法。在__exit__()方法中,有self.close()语句,因此,在调用上下文管理器时,我们就不用明文关闭文件了。可以说,任何定义了__enter__()方法和__exit__()方法的对象都可以用于上下文管理器。
3.pickle包——咸菜小罐
在大航海时代,长期处于海路船运生活的探险家们为了补充蔬菜里的营养物质,常把蔬菜腌制成咸菜装在罐子里带走,python中的pickle包正是取自此意。在编程中,常常产生需要的对象,但计算机关机或程序结束,这些对象都会消失,为了存储对象,只要把对象腌制成pickle罐装带走就好:
要腌咸菜,我们只需要两步:
① 我们将对象在内存中的数据抓取出来并转换成一个有序的文本,即所谓的序列化(serialization)。
② 将文本存入文件,等需要时从文件中读出文本再放入内存就能获得原有的对象。
使用dumps()方法:
使用dump()方法,可以缩短一行:
同时在默认地址下创建了文件。有了这个文件,我们就可以在需要的时候读取对象了(∩_∩)。
读取和存储的过程刚好相反,首先要从文件里读出文本,然后使用pickle的loads()方法将字符串形式的文本转换成对象,或者使用load()方法,省略一步:
5.2 时间
1.time包
在硬件基础上,计算机可以提供挂钟时间(wall clock time):从某个时间点到现在的时间间隔。
clock()方法:
import time
start = time.clock()
for i in range(100):
print(i**2)
end = time.clock()
print(end - start)
运行后打印:
上述程序调用了两次clock()方法,从而测量出镶嵌在他俩之间的程序运行所需的时间,需要注意的是,这在Unix系统上返回的是CPU时间,当CPU处于闲置状态时处理器时间会暂停,在Windows系统上返回的则是挂钟时间。
sleep()方法:
from time import sleep
sleep(10)
print('wakeup')
运行10秒后,打印出字符串‘wakeup‘。
time包还定义了struct_time对象,该对象将挂钟时间转换为年/月/日/时/分/秒,存储在该对象的各个属性中,比如tm_year,tm_mon,tm_mday..下面总结了几种将挂钟时间转换为struct_time对象的方法:
st = time.gmtime() #返回struct_time格式的UTC时间
st = time.localtime() #返回struct_time格式的当地时间,当地时间根据系统环境决定
我们也可以反过来,把一个struct_time对象转换为time对象:
s = time.mktime(st) #将struct_time格式转换成挂钟时间
2.datetime包
datetime包是基于time包的一个高级包,使用起来更加便利。
date可以理解为由date与time两部分组成,date是指年月日构成的日期,time是指时分秒构成一天内具体24小时内的时刻。因此,datetime包包含了两类,datetime.date和datetime.time,也可以把两个类结合在一起使用,即datetime.datetime。下面开始介绍datetime.datetime类,datetim.date,datetime.time与datetime.datetime类似。
要表达一个时刻,可以:
import datetime
t = datetime.datetime(2012,12,21,12,21)
print(t)
打印:
对象t有以下属性:
hour-小时,minute-分,second-秒,millisecond-毫秒,microsecond-微秒
year-年,month-月,day-日,weekly-星期
借助datetime包,我么可以进行时间间隔运算。它包含一个专门的代表时间间隔的分类,即timedelta,一个datetime.datetime时刻加上一段时间,就有了一个新的时刻:
import datetime
t = datetime.datetime(2012,9,3,21,30)
t_next = datetime.datetime(2012,9,5,23,30)
delta1 = datetime.timedelta(seconds = 600)
delta2 = datetime.timedelta(weeks = 3)
print(t + delta1)
print(t + delta2)
print(t_next - t)
打印结果:
除此之外还能进行比较运算:
print(t > t_next)
打印结果:
3.日期格式
对于包含时间信息的字符串,我么可以借助datetime包,把它转换成datetime类的对象,在其中运用了strptime()方法:
strptime(),按照特定时间格式将字符串转换为时间类型。
from datetime import datetime
str = 'output-1991-02-13-030000.txt'
format = 'output-%Y-%m-%d-%H%M%S.txt'
t = datetime.strptime(str,format)
print(t)
打印结果:
反其道而行之,运用strftime()方法:
strftime():根据区域设置格式化本地时间/日期,函数的功能将时间格式化,或者说格式化一个时间字符串
from datetime import datetime
format = '%Y-%m-%d %H:%M'
t = datetime(2012,9,3,12,30)
print(t.strftime(format))
打印结果:
除了表达年月日时分秒的特殊符号,还有代表其他不同信息的符号:
%A 表示英文的星期几
%a 表示简写的英文的星期几
%I 表示小时,12小时制
%p 表示上午或者下午,AM或者PM
%f 表示毫秒
※如果想在格式中表达%这个字符本身,而不是特殊符号,那可以使用%%
5.3正则表达式
1.正则表达式
正则表达式(regular expression)的主要功能是从字符串(string)中通过特定的模式,搜索希望找到的内容。python中可以使用包re来处理正则表达式。
import re
m = re.search('[0-9]','abcd4ef')
print(m.group(0))
re.search()接受两个参数,第一个参数‘[0-9]’就是我们说的正则表达式,它告诉python,‘我们需要从字符串中找到从0到9的任意一个数字字符。’
re.search()如果在第二个参数,即待查找的字符串中找到了符合要求的字符,就会返回一个对象m,我们可以通过m.group()方法查看搜索到的结果,若没有找到符合要求的字符,re.search()会返回None。
除了search方法外,re还提供了其他搜索方法:
m = re.search() #搜索整个字符串,知道发现符合的子字符串
m = re.match() #从开头开始检查字符串是否符合正则表达式,必须从字符串的第一个字符就开始相符
str = re.sub(pattern,replacement,string) #sub()方法利用正则表达式pattern与字符串string对比,对搜索到的相符字符串,用replacement进行替换
str = re.split() #根据正则表达式分割字符串,将分割后的子字符串都放在一个list中返回
str = re.findall()#根据正则表达式搜索字符串,将所有符合条件的子字符串放在一个list中返回
2.写一个正则表达式
. #任意一个字符
a|b #字符a或者字符b
[afg] #a或者g或者f的一个字符
[0-4] #0~4范围内的一个字符
[a-f] #a到f范围内的一个字符
[^m] #除了m的一个字符
\s #一个空格
\S #一个非空格
\d #一个数字,相当于[0-9]
\D #一个非数字,相当于[^0-9]
\w #一个字母或者数字下划线,相当于[_0-9a-zA-Z]
\W #一个非字母非数字非下划线,相当于[^_0-9a-zA-Z]
在表达某种形式的重复时,有:
* #重复超过0次或更多次
+ #重复1次或超过1次
? #重复0次或1次
{m} #重复m次
{m,n} #重复m到n次,小于m次的重复和大于n次的重复都不符合条件
正则表达式位置符号:
^ #字符串起始的位置
$ #字符串结尾的位置
3.进一步提取
有时我们想对结果进行进一步的提炼,比如我们想从字符串content = ‘abcd_output_1994_abcd_1912_abcd’中提取信息:
import re
content = 'abcd_output_1994_abcd_1912_abcd'
p = 'output_\d{4}'
m = re.search(p,content)
print(m.group(0))
上面的正则表达式可以筛出:
如果想进一步筛出1994这四个字符,可以在正则表达式上给目标加上括号:
import re
content = 'abcd_output_1994_abcd_1912_abcd'
p = 'output_(\d{4})'
m = re.search(p,content)
print(m.group(1))
这个正则表达式中的()括起来的部分表达式称为群(group)一个正则表达式中可以有多个群。我们用group(number)的方法来查询群,需要注意的是,group(0)是整个正则表达式的匹配结果,group(1)是第一个群。
所以修改后的程序打印的结果是:
除了以默认群序号查找群外,我们还可以命名群名的方式查询:
import re
content = 'abcd_output_1994_abcd_1912_abcd'
p = 'output_(?P<year>\d{4})'
m = re.search(p,content)
print(m.group('year'))
正则表达式中(?P<year>\d{4})括住了一个群,并把它命名成’year‘,这样在打印语句中通过m.group('year')即群名查找方法可以找到我们所需的年份,故打印结果: