计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护。为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。在Python中,一个.py文件就称之为一个模块(Module)。
模块分类:
内置模块python安装时自带的
扩展模块别人写好的,安装之后可以直接使用
djangotornado(框架)
自定义模块自己写的模块
提高了代码的可维护性。
当一个模块编写完毕,就可以被其他地方引用。
使用模块可以避免函数名和变量名冲突。
time模块
具体用法:
importrandominp_money=float(input('红包金额:'))inp_count=int(input('红包个数:'))defred_packet(money,count):li=[]money=int(money*100)money_site=random.sample(range(1,money),count-1)money_site.extend([0,money])money_site=sorted(money_site)foriinrange(count):li.append(round((money_site[i+1]-money_site[i])*0.01,2))returnli#上面的定义li列表、for循环以及return可以简写成下面一行。#return[round((sorted(money_site)[i+1]-sorted(money_site)[i])*0.01,2)foriinrange(count)]ret=red_packet(inp_money,inp_count)print(ret)ViewCode利用随机数随机生成4位验证码,并带模糊效果
fromPILimportImage,ImageDraw,ImageFont,ImageFilterimportrandom#随机字母:defrndChar():returnchr(random.randint(48,57))#随机颜色1:defrndColor():return(random.randint(64,255),random.randint(64,255),random.randint(64,255))#随机颜色2:defrndColor2():return(random.randint(32,127),random.randint(32,127),random.randint(32,127))#240x60:width=60*4height=60image=Image.new('RGB',(width,height),(255,255,255))#创建Font对象:font=ImageFont.truetype('ariblk.ttf',40)#创建Draw对象:draw=ImageDraw.Draw(image)#填充每个像素:forxinrange(width):foryinrange(height):draw.point((x,y),fill=rndColor())#输出文字:fortinrange(4):draw.text((60*t+10,10),rndChar(),font=font,fill=rndColor2())#模糊:image=image.filter(ImageFilter.BLUR)image.save('code.jpg','jpeg')3.OS模块(是与操作系统交互的一个接口)#有的文件可能转义可能会出现问题,一般要在双引号前加r,取消转义,或者用双斜杠表示
#说明,第一种方式采用了递归,虽然结果上也实现了,但是它相对来说比较耗内存。而第二种方式利用堆和栈的方式来说更加的友好
1sys.argv命令行参数是一个List,第一个元素是程序本身路径2sys.exit(n)退出程序,正常退出时exit(0)3sys.version获取Python解释程序的版本信息4sys.maxint最大的Int值5sys.path返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值6sys.platform返回操作系统平台名称5.序列化模块序列化:
把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。
序列化目的
序列化有三个模块json和pickle,shelve
json所有编程语言都通用的序列化格式,但是它支持的数据类型非常有限(只支持数字,字符串,序列,字典等,不支持元祖)
pickle只能在python语言的程序之间传递数据使用,它支持python中所有数据类型
shelve在py3之后才有,python专有的序列化模块,只针对文件。它只提供一个open方法,并且只能用字典形式访问内容
json
Json模块提供了四个功能:dumps、loads,这两个只在内存中操作数据,主要在网络传输中使用,和多个数据类型与文件打交道
dump、load,这两个是直接将对象序列化之后写入文件,它依赖于一个文件句柄
importjsondic={'k1':'v1','k2':'v2','k3':'v3'}str_dic=json.dumps(dic)#将字典转换成字符串,转换后的字典中的元素是由双引号表示的print(str_dic,type(str_dic))#{"k1":"v1","k2":"v2","k3":"v3"}
#json如果要写入多个元素,应先将元素dumps序列化,再f.write(序列化+‘\n’)写入文件。读的时候先按行读取,再使用loads将读出来的字符串转换成相应数据类型。
pickle(可以把python中的任意数据类型序列化)
在硬盘上存储文件有很多种方法,文本文件只是其中一种,如果想存储列表或者对象之类的内容,可以把对象转换成字符串的形式写入文本文件,但是如果要从文件中回复对象,则这个就复杂化了。而python提供的pickle恰好能做到这一点:
#通过pickle存储python原生对象:importpickleD={'a':1,'b':2}F=open('datafile.pkl','wb')pickle.dump(D,F)#pickle.dump()可以把任意对象序列化成一个bytes,然后就可以把bytes写入文件F.close()#取回字典,再用pickle模块中load函数进行一次重建F=open('datafile.pkl','rb')E=pickle.load(F)F.close()importpicklefile='wish.data'lis=['apple','banban']f=open(file,'wb')pickle.dump(lis,f)f.close()dellisf=open(file,'rb')storedlis=pickle.load(f)print(storedlis)#又得到了列表关于序列化自定义类的对象:
classA:def__init__(self,name,age):self.name=nameself.age=agea=A('luffy',18)#importjson#json.dumps(a)#报错,说明json无法存储实例化对象importpickleret=pickle.dumps(a)print(ret)#打印出来的是一串字节obj=pickle.loads(ret)print(obj)#打印出对象地址print(obj.__dict__)#{'name':'luffy','age':18}在load的时候,必须拥有被load数据类型对应的类在内存里面
python专有的序列化模块,只针对文件,只提供了一个open方法,且是用key来访问的,使用起来和字典类似。
importshelvef=shelve.open('a.txt')f['key']={'int':10,'float':9.5,'string':'Sampledata'}f['ds']='范围分为we分我发'f.close()#直接对文件句柄进行操作,就可以存储文件,而且程序会给我们自动创建三个后缀为dir,bak,dat的文件,其中以bat结尾的文件存储的就是b字节数据类型的数据f1=shelve.open('a.txt')a=f1['ds']#用key直接取出存储的内容,如果key不存在则会报错f1.close()print(a)#设置只读模式f2=shelve.open('a.txt',flag='r')f2['key']['float']=3.14#修改结构中得值,不可以f2['space']='dwd'#覆盖原来的结构,可以f1.close()f3=shelve.open('a.txt')b=f3['key']['float']#对结构的值作修改,但是失败了f3.close()print(b)#9.56.hashlib模块摘要算法,也称哈希算法,它能将字符串转成数字,不同的字符串转成的数字一定不同,通常用16进制表示。无论在哪台机器上,在什么时候计算,对相同的字符串结果总是一样的
任何摘要算法都是把无限多的数据集合映射到一个有限的集合中。因此两个不同的数据通过某个摘要算法也可能得到相同的摘要,这种情况被称为碰撞
用处:
密文验证的时候加密
文件的一致性校验
#md5算法:业界通用算法
密文验证的时候加密:
#该函数一次性全部交验,如果文件较大,则耗时较大importhashlibdefcheck(filename):md5obj=hashlib.md5()withopen(filename,'rb')asf:content=f.read()md5obj.update(content)returnmd5obj.hexdigest()#该函数对于较大的文件,一次性以一定的字节数读取验证来验证一致性defcheck(filename):md5obj=hashlib.md5()withopen(filename,'rb')asf:whileTrue:content=f.read(1024)ifcontent:md5obj.update(content)else:#如果文件为空breakreturnmd5obj.hexdigest()ret1=check('file1.txt')ret2=check('file2.txt')print(ret1)print(ret2)那么问题来了,如何验证两个文件的一致性呢?
#创建ini文件importconfigparserconfig=configparser.ConfigParser()config["DEFAULT"]={'luffy':'香蕉人','zero':'三把刀','sanzhi':'秋刀鱼'}config['name']={'rojie':'onepiece','BB':'c','dd':'N'}#config['www.onepiece.online']={'我就试试集合行不行'}#报错,只能是字典形式config['www.onepiece.online']={'我就试试集合行不行':'不行啊'}withopen('one.ini','w')asf:config.write(f)写入后内容形式(这里我是直接用电脑自带的文本阅读器打开的,默认是gbk格式,用其他阅读器非gbk会产生乱码):
[DEFAULT]zero=三把刀sanzhi=秋刀鱼luffy=香蕉人
[name]dd=Nbb=crojie=onepiece
[www.onepiece.online]我就试试集合行不行=不行啊
增删改操作
#增删改操作importconfigparserconfig=configparser.ConfigParser()config.read('one.ini')#删除节'name'config.remove_section('name')#删除节下的某个value值config.remove_option('www.onepiece.online','我就试试集合行不行')#判断是否存在某个标题print(config.has_section('name'))#判断标题section1下是否有userprint(config.has_option('www.onepiece.online','我就试试集合行不行'))#添加一个标题config.add_section('EGG')#在标题EGG下添加name=egon,age=18的配置config.set('EGG','name','egon')config.set('EGG','age','18')总结:
#section可以直接操作他的对象来获取所有的节信息
#option可以通过找到的节来查看所有的项
不会帮你自动添加日志的内容,只能根据程序员写的代码完成功能
可以通过一个参数去控制全局的日志输出情况
可以帮助开发者同时向文件和屏幕输出内容
logging模块提供5中日志级别,从低到高一次:debuginfowarningerrorcritical
默认是从warning模式开始显示
日志级别CRITICAL=50#FATAL=CRITICALERROR=40WARNING=30#WARN=WARNINGINFO=20DEBUG=10默认级别为warning,它会默认打印在终端上
简单用法:basicconfig
#默认情况下只显示警告(warning)及警告级别以上信息importlogginglogging.basicConfig(level=logging.DEBUG,format='%(asctime)s%(filename)s[line:%(lineno)d]%(levelname)s%(message)s',datefmt='%a,%d%b%y%H:%M:%S',filename='userinfo.log')logging.debug('debugmessage')#debug调试模式级别最低logging.info('infomessage')#info显示正常信息logging.warning('warningmessage')#warning显示警告信息logging.error('errormessage')#error显示错误信息logging.critical('criticalmessage')#critical显示严重错误信息---WARNING:root:warningmessage---ERROR:root:errormessage---CRITICAL:root:criticalmessage---WARNING:root:warningmessagelogging.basicconfig()函数可配参数:
#Logger产生日志对象#Handler接收日志然后控制打印到不同地方:#FileHandler用来打印到文件中,#StreamHandler用来打印到终端#Filter过滤日志对象#Formatter指定日志显示格式logger对象配置:
counter:计数器
deque:双端排列,可以快速从另外一侧追加对象
namedtuple:生成可以使用名字来访问元素内容的tuple
orderdict:有序字典
defaultdict:带有默认值的字典
namedtuple:
fromcollectionsimportnamedtuplepoint=namedtuple('point',['x','y','z'])p=point(1,4,9)print(p.x)#1print(p.z)#9#用来计算长方体体积square=namedtuple('length',('x','y','z'))v=square(5,2,8)volume=v.x*v.y*v.zprint(volume)#80deque:
它是为了实现插入和删除操作的双向列表,适用于队列和栈
fromcollectionsimportdequelis=deque(['a','c','b'])lis.append(3)lis.appendleft(5)print(lis)#deque([5,'a','c','b',3])#这里直接用list()可以转换成列表形式Counter:
它的作用是用来跟踪值出现的次数,属于一个无序的容器类型,以字典的键值对形式存储
基本用法:
fromcollectionsimportCounterc=Counter('abcdeabcdabcaba')print(dict(c))#{'e':1,'b':4,'d':2,'a':5,'c':3}print(c['a'])#5print(c['b'])#4计数器的更新,包含增加(update)和减少(subtract)两种
fromcollectionsimportCounter#updatec=Counter('smile')c.update('lie')print(c['e'])#2d=Counter('beautiful')f=Counter('bee')d.update(f)print(d['e'])#3#subtractc=Counter('smile')c.subtract('lie')print(c['e'])#0d=Counter('beautiful')f=Counter('bee')d.subtract(f)print(d['e'])#-1键的修改和删除(del)
fromcollectionsimportCounterc=Counter("abcdcba")c['a']=0print(dict(c))#{'d':1,'a':0,'c':2,'b':2}delc['b']print(dict(c))#{'a':0,'c':2,'d':1}算数和集合操作
+、-、&、|操作也可以用于Counter。其中&和|操作分别返回两个Counter对象各元素的最小值和最大值。需要注意的是,得到的Counter对象将删除小于1的元素。
c=Counter(a=8,b=1)d=Counter(a=5,b=2)print(dict(c+d))#{'a':13,'b':3}print(dict(c-d))#{'a':3}注意,它只保留正数计数的元素print(dict(c&d))#{'a':5,'b':1}求交集,min(c[x],d[x])print(dict(c|d))#{'b':2,'a':8}求并集,max(c[x],d[x])Counter类常用操作
#对['a','2',2,4,5,'2','b',4,7,'a',5,'d','a','z']该列表的数据进行计数统计
Orderedict
保持key的顺序
fromcollectionsimportOrderedDictd=dict([('a',3),('b',5),('c',3)])print(d)#{'b':5,'c':3,'a':3}d=OrderedDict([('a',3),('b',5),('c',3)])print(d)#OrderedDict([('a',3),('b',5),('c',3)])#给这个样子感觉作用不大啊,用dict转型过来顺序又变了对一个字典进行有序排序:
fromcollectionsimportOrderedDictordered_dict=OrderedDict()dic={4:'xxx',1:'xxx',2:'xxx',}forkeyinsorted(dic):ordered_dict[key]=dic[key]print(ordered_dict)defaultdict(默认字典,是给字典中的value值设置默认值)
它最大的好处在于永远不会在你使用key获取值的时候报错
有如下值集合[11,22,33,44,55,66,77,88,99,90...],将所有大于66的值保存至字典的第一个key中,将小于66的值保存至第二个key的值中。
fromcollectionsimportdefaultdictvalues=[11,22,33,44,55,66,77,88,99,90]my_dict=defaultdict(list)forvalueinvalues:ifvalue>66:my_dict['k1'].append(value)else:my_dict['k2'].append(value)print(dict(my_dict))