python-常用模块

re模块

re模块的常用用法

import re

# 字符串
# 匹配
# findall  *****
# ret = re.findall('\d+','19874ashfk01248')
# print(ret)  # 参数 返回值类型:列表 返回值个数:1 返回值内容:所有匹配上的项
# ret1 = re.findall('\s+','19874ashfk01248')
# print(ret1)
# search   *****
# ret2 = re.search('\d+','@$19874ashfk01248')
# print(ret2) #  返回值类型: 正则匹配结果的对象  返回值个数:1 如果匹配上了就返回对象
# if ret2:print(ret2.group()) # 返回的对象通过group来获取匹配到的第一个结果
# ret3 = re.search('\s+','19874ashfk01248')
# print(ret3) #  返回值类型: None   如果没有匹配上就是None
# match  **
# ret4 = re.match('\d+','19874ashfk01248')
# print(ret4)
# ret5 = re.match('\d+','%^19874ashfk01248')
# print(ret5)


# 替换 replace
# sub ***
# print('replace789,24utdeedeeeeshf'.replace('e','H',3))
# ret = re.sub('\d+','H','replace789nbc2xcz392zx')
# print(ret)
# ret = re.sub('\d+','H','replace789nbc2xcz392zx,48495',1)
# print(ret)
# subn ***
# ret = re.subn('\d+','H','replace789nbc2xcz392zx')
# print(ret)

# 切割
# split ***
# print('alex|83|'.split('|'))
# ret = re.split('\d+','alex83egon20taibai40')
# print(ret)

# 进阶方法 - 爬虫\自动化开发
# compile ***** 时间效率
# re.findall('-0\.\d+|-[1-9]+(\.\d+)?','alex83egon20taibai40')  --> python解释器能理解的代码 --> 执行代码
# ret = re.compile('-0\.\d+|-[1-9]\d+(\.\d+)?')
# res = ret.search('alex83egon-20taibai-40')
# print(res.group())
# 节省时间 : 只有在多次使用某一个相同的正则表达式的时候,这个compile才会帮助我们提高程序的效率

# finditer ***** 空间效率
# print(re.findall('\d','sjkhkdy982ufejwsh02yu93jfpwcmc'))
# ret = re.finditer('\d','sjkhkdy982ufejwsh02yu93jfpwcmc')
# for r in ret:
#     print(r.group())

 random模块

 random模块常用方法

import random
# 随机 : 在某个范围内取到每一个值的概率是相同的
# 随机小数
# print(random.random())  # 0-1之内的随机小数
# print(random.uniform(1,5)) # 任意范围之内的随机小数

# 随机整数 *****
# print(random.randint(1,2)) # [1,2] 包含2在内的范围内随机取整数
# print(random.randrange(1,2)) # [1,2)不包含2在内的范围内随机取整数
# print(random.randrange(1,10,2)) # [1,10)不包含10在内的范围内随机取奇数

# 随机抽取
# 随机抽取一个值
# lst = [1,2,3,'aaa',('wahaha','qqxing')]
# ret = random.choice(l)
# print(ret)
# 随机抽取多个值
# ret = random.sample(lst,2)
# print(ret)

# 打乱顺序  在原列表的基础上做乱序
# lst = [1,2,3,'aaa',('wahaha','qqxing')]
# random.shuffle(lst)
# print(lst)

# 抽奖 \ 彩票 \发红包 \验证码 \洗牌

 

# 生成随机验证码
# 4位数字的
import random
# 0-9
# 基础版本
# code = ''
# for i in range(4):
#     num = random.randint(0,9)
#     code += str(num)
# print(code)

# 函数版本
# def rand_code(n=4):
#     code = ''
#     for i in range(n):
#         num = random.randint(0,9)
#         code += str(num)
#     return code
#
# print(rand_code())
# print(rand_code(6))

# 6位 数字+字母
# print(chr(97))
# print(chr(122))
# import random

# 基础版
# code = ''
# for i in range(6):
#     rand_num = str(random.randint(0,9))
#     rand_alph = chr(random.randint(97,122))
#     rand_alph_upper = chr(random.randint(65,90))
#     atom_code = random.choice([rand_num,rand_alph,rand_alph_upper])
#     code += atom_code
# print(code)

# 函数版
# def rand_code(n=6):
#     code = ''
#     for i in range(n):
#         rand_num = str(random.randint(0,9))
#         rand_alph = chr(random.randint(97,122))
#         rand_alph_upper = chr(random.randint(65,90))
#         atom_code = random.choice([rand_num,rand_alph,rand_alph_upper])
#         code += atom_code
#     return code
#
# ret = rand_code()
# print(ret)

# 数字/数字+字母
# def rand_code(n=6 , alph_flag = True):
#     code = ''
#     for i in range(n):
#         rand_num = str(random.randint(0,9))
#         if alph_flag:
#             rand_alph = chr(random.randint(97,122))
#             rand_alph_upper = chr(random.randint(65,90))
#             rand_num = random.choice([rand_num,rand_alph,rand_alph_upper])
#         code += rand_num
#     return code
#
# ret = rand_code(n = 4)
# print(ret)

# ***** 永远不要创建一个和你知道的模块同名的文件名

#函数 : 发红包 : 200块钱 , 10个
生成随机验证码

 

time模块

表示时间的三种方式

  •  时间戳时间,格林威治时间,float数据类型 给机器用的

 

  • 结构化时间,时间对象 上下两种格式的中间状态

    

  • 格式化时间,字符串时间,str数据类型 给人看的

    

%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 当前时区的名称
%% %号本身

python中时间日期格式化符号:
python中时间日期格式化符号

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)

几种格式之间的转换

 

#几种格式之间的转换

# print(time.time())
# print(time.localtime(1500000000))
# print(time.localtime(2000000000))
# time_obj = time.localtime(3000000000)
# format_time = time.strftime('%y-%m-%d %H:%M:%S',time_obj)
# print(format_time)

# 2008-8-8
# struct_time = time.strptime('2008-8-8','%Y-%m-%d')
# print(struct_time)
# print(time.mktime(struct_time))

# 计算本月一号的时间戳时间
# 结构化时间
# struct_time = time.localtime()
# struct_time = time.strptime('%s-%s-1'%(struct_time.tm_year,struct_time.tm_mon),'%Y-%m-%d')
# print(time.mktime(struct_time))
# 格式化时间
# ret = time.strftime('%Y-%m-1')
# struct_time = time.strptime(ret,'%Y-%m-%d')
# print(time.mktime(struct_time))

 datetime模块

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天'))

 

sys模块

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

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

 

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的大小

 

logging模块

  • 日志格式的规范
  •  操作的简化
  • 日志的分级管理

函数式简单配置

import logging  
logging.debug('debug message')  # 调式模式
logging.info('info message')    # 基础信息
logging.warning('warning message')  #警告
logging.error('error message')    # 错误
logging.critical('critical message') # 严重错误

默认情况下Python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG),默认的日志格式为日志级别:Logger名称:用户输出消息

灵活配置日志级别,日志格式,输出位置:


import logging

file_handler = logging.FileHandler(filename='test.log', mode='a', encoding='utf-8',)
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
handlers=[file_handler,],
level=logging.ERROR
)

logging.error('你好')
format='%(asctime)s #时间 %(filename)s #错误的文件 [line:%(lineno)d] # 哪一行的错误 %(levelname)s # 什么级别的错误 %(message)s', # 错误信息

参数配置

logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:

filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中。
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
format:指定handler使用的日志显示格式。
datefmt:指定日期时间格式。
level:设置rootlogger(后边会讲解具体概念)的日志级别
stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。

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

 

日志切割

日志切割
import time
from logging import handlers

sh = logging.StreamHandler()
# rh = handlers.RotatingFileHandler('../log/test.log', maxBytes=1024, backupCount=5, encoding='utf-8') # 根据大小切
# maxBytes 最大的字节数超过就切, backupCount=5 最多备份5个,切掉第6个就删掉,把第6个命名第5个
fh = handlers.TimedRotatingFileHandler(filename='../log/test2.log', when='s', interval=1, encoding='utf-8') #根据时间切
# interval=5 按5秒切一次, when='s' when='M' 按分钟 when='H' 按小时 when='D' 按天切 when='W' 按周切

logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
handlers=[sh,fh],
level=logging.INFO
)

while True:
logging.info('111111111')

 

 

logger对象配置


# logger对象的形式来操作日志文件

# 创建一个logger对象
# 创建一个文件管理操作符
# 创建一个屏幕管理操作符
# 创建一个日志输出的格式

# 文件管理操作符 绑定一个 格式
# 屏幕管理操作符 绑定一个 格式

# logger对象 绑定 文件管理操作符
# logger对象 绑定 屏幕管理操作符

import logging
# 创建一个logger对象
logger = logging.getLogger()
# 创建一个文件管理操作符
fh = logging.FileHandler('logger.log',encoding='utf-8')
# 创建一个屏幕管理操作符
sh = logging.StreamHandler()
# 创建一个日志输出的格式
format1 = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# 文件管理操作符 绑定一个 格式
fh.setFormatter(format1)
# 屏幕管理操作符 绑定一个 格式
sh.setFormatter(format1)
logger.setLevel(logging.DEBUG)
# logger对象 绑定 文件管理操作符
# logger.addHandler(fh)
# logger对象 绑定 屏幕管理操作符
logger.addHandler(sh)

logger.debug('debug message') # 调试模式
logger.info('我的信息') # 基础信息
logger.warning('warning message') # 警告
logger.error('error message') # 错误
logger.critical('critical message')# 严重错误

 

hashlib模块

Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。

什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)

我们以常见的摘要算法MD5为例,计算出一个字符串的MD5值:

import hashlib
 
md5 = hashlib.md5()
md5.update('how to use md5 in python hashlib?')
print md5.hexdigest()

计算结果如下:
d26a53750bc40b38b65a520292f69306

如果数据量很大,可以分块多次调用update(),最后计算的结果是一样的:

md5 = hashlib.md5()
md5.update('how to use md5 in ')
md5.update('python hashlib?')
print md5.hexdigest()

MD5是最常见的摘要算法,速度很快,生成结果是固定的128 bit字节,通常用一个32位的16进制字符串表示。另一种常见的摘要算法是SHA1,调用SHA1和调用MD5完全类似:

import hashlib
 
sha1 = hashlib.sha1()
sha1.update('how to use sha1 in ')
sha1.update('python hashlib?')
print sha1.hexdigest()

SHA1,通常用一个40位的16进制字符串表示,算法相对复杂 计算速度也慢, 比SHA1更安全的算法是SHA256和SHA512,不过越安全的算法越慢,而且摘要长度更长。

摘要算法应用

1.登录的密文验证

密码不能解密,但可以撞库

# 数据库 - 撞库
# 111111 --> 结果
# 666666
# 123456
# alex3714 --> aee949757a2e698417463d47acac93df

# s1 = '123456'
# md5_obj = hashlib.md5()
# md5_obj.update(s1.encode('utf-8'))
# res = md5_obj.hexdigest()
# print(res,len(res),type(res))
View Code

加盐

# 加盐  # wind3714  d3cefe8cdd566977ec41566f1f11abd9
# md5_obj = hashlib.md5('任意的字符串作为盐'.encode('utf-8'))
# md5_obj.update(s1.encode('utf-8'))
# res = md5_obj.hexdigest()
# print(res,len(res),type(res))
# wind登录 alex3714|d3cefe8cdd566977ec41566f1f11abd9


# wind|d3cefe8cdd566977ec41566f1f11abd9
# 张三|d3cefe8cdd566977ec41566f1f11abd8  123456
# 鞠莹莹|d3cefe8cdd566977ec41566f1f11abd8 123456
View Code

动态加盐

# 遇到恶意用户 注册500个账号,我们采用动态加盐
# 张三|123456  '任意的字符串作为盐'.encode('utf-8') d3cefe8cdd566977ec41566f1f11abd8
# 李四|111111
# eee|alex3714

# 动态加盐
# username = input('username : ')
# passwd = input('password : ')
# md5obj = hashlib.md5(username.encode('utf-8'))
# md5obj.update(passwd.encode('utf-8'))
# print(md5obj.hexdigest())
# ee838c58e5bb3c9e687065edd0ec454f
View Code

 

2.文件的一致性校验

# md5_obj = hashlib.md5()
# with open('5.序列化模块_shelve.py','rb') as f:
#     md5_obj.update(f.read())
#     ret1 = md5_obj.hexdigest()
#
# md5_obj = hashlib.md5()
# with open('5.序列化模块_shelve.py.bak','rb') as f:
#     md5_obj.update(f.read())
#     ret2 = md5_obj.hexdigest()
# print(ret1,ret2)
View Code

 大文件的一致性校验

# 写成一个函数
# 参数 : 文件1的路径,文件2的路径,默认参数 = 1024000
# 计算这两个文件的md5值
# 返回它们的一致性结果 T/F

1 import hashlib
 2 md5_obj = hashlib.md5()
 3 import os
 4 filesize = os.path.getsize('filename')  #文件大小
 5 f = open('filename','rb')
 6 while filesize>0:
 7     if filesize > 1024:
 8         content = f.read(1024)
 9         filesize -= 1024
10     else:
11         content = f.read(filesize)
12         filesize -= filesize
13     md5_obj.update(content)
14 # for line in f:
15 #     md5_obj.update(line.encode('utf-8'))
16 md5_obj.hexdigest()
文件校验(检测文件改变了没)
View Code

 

序列化模块

什么叫序列化——将原本的字典、列表等内容转换成一个字符串的过程就叫做序列化

 

 

json

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

import json
# json格式的限制1,json格式的key必须是字符串数据类型
# json格式中的字符串只能是""

# 如果是数字为key,那么dump之后会强行转成字符串数据类型
# dic = {1:2,3:4}
# str_dic = json.dumps(dic)
# print(str_dic)
# new_dic = json.loads(str_dic)
# print(new_dic)

# json是否支持元组,对元组做value的字典会把元组强制转换成列表
# dic = {'abc':(1,2,3)}
# str_dic = json.dumps(dic)
# print(str_dic)
# new_dic = json.loads(str_dic)
# print(new_dic)

# json是否支持元组做key,不支持
# dic = {(1,2,3):'abc'}
# str_dic = json.dumps(dic)  # 报错

# 对列表的dump
# lst = ['aaa',123,'bbb',12.456]
# with open('json_demo','w') as f:
#     json.dump(lst,f)
# with open('json_demo') as f:
#     ret = json.load(f)
#     print(ret)

# 能不能多次dump数据到文件里,可以多次dump但是不能load出来了
# dic = {'abc':(1,2,3)}
# lst = ['aaa',123,'bbb',12.456]
# with open('json_demo','w') as f:
#     json.dump(lst,f)
#     json.dump(dic,f)
# with open('json_demo') as f:
#     ret = json.load(f)
#     print(ret)

# 想dump多个数据进入文件,用dumps
# dic = {'abc':(1,2,3)}
# lst = ['aaa',123,'bbb',12.456]
# with open('json_demo','w') as f:
#     str_lst = json.dumps(lst)
#     str_dic = json.dumps(dic)
#     f.write(str_lst+'\n')
#     f.write(str_dic+'\n')

# with open('json_demo') as f:
#     for line in f:
#         ret = json.loads(line)
#         print(ret)

# 中文格式的 ensure_ascii = False
# dic = {'abc':(1,2,3),'country':'中国'}
# ret = json.dumps(dic,ensure_ascii = False)
# print(ret)
# dic_new = json.loads(ret)
# print(dic_new)

# with open('json_demo','w',encoding='utf-8') as f:
#     json.dump(dic,f,ensure_ascii=False)

# json的其他参数,是为了用户看的更方便,但是会相对浪费存储空间
# import json
# data = {'username':['李华','二愣子'],'sex':'male','age':16}
# json_dic2 = json.dumps(data,sort_keys=True,indent=4,separators=(',',':'),ensure_ascii=False)
# print(json_dic2)

# set不能被dump/dumps
View Code

pickle

用于序列化的两个模块

 

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

 

pickle模块提供了四个功能:dumps、dump(序列化,存)、loads(反序列化,读)、load  (不仅可以序列化字典,列表...可以把python中任意的数据类型序列化

# pickle
dic = {1:(12,3,4),('a','b'):4}
import  pickle

# dump的结果是bytes,dump用的f文件句柄需要以wb的形式打开,load所用的f是'rb'模式
# 支持几乎所有对象的序列化
# 对于对象的序列化需要这个对象对应的类在内存中
# 对于多次dump/load的操作做了良好的处理

# pic_dic = pickle.dumps(dic)
# print(pic_dic)    # bytes类型
# new_dic = pickle.loads(pic_dic)
# print(new_dic)

# pickle支持几乎所有对象的
# class Student:
#     def __init__(self,name,age):
#         self.name = name
#         self.age = age
#
# alex = Student('alex',83)
# ret = pickle.dumps(alex)
# 小花 = pickle.loads(ret)
# print(小花.name)
# print(小花.age)

# class Student:
#     def __init__(self,name,age):
#         self.name = name
#         self.age = age
#
# alex = Student('alex',83)
# with open('pickle_demo','wb') as f:
#     pickle.dump(alex,f)
# with open('pickle_demo','rb') as f:
#     旺财 = pickle.load(f)
#     print(旺财.name)

# 学员选课系统  pickle模块来存储每个学员的对象

# with open('pickle_demo','wb') as f:
#     pickle.dump({'k1':'v1'}, f)
#     pickle.dump({'k11':'v1'}, f)
#     pickle.dump({'k11':'v1'}, f)
#     pickle.dump({'k12':[1,2,3]}, f)
#     pickle.dump(['k1','v1','l1'], f)

# with open('pickle_demo','rb') as f:
#     while True:
#         try:
#             print(pickle.load(f))
#         except EOFError:
#             break
pickle

既然pickle如此强大,为什么还要学json呢?

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

 

collections模块

数据类型的扩展模块

在内置数据类型(dict、list、set、tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter、deque、defaultdict、namedtuple和OrderedDict等。

1.namedtuple: 生成可以使用名字来访问元素内容的tuple

2.deque: 双端队列,可以快速的从另外一侧追加和推出对象

3.Counter: 计数器,主要用来计数

4.OrderedDict: 有序字典

5.defaultdict: 带有默认值的字典

 

什么是队列?

# 先进先出
# import queue
# q = queue.Queue()
# print(q.qsize())
# q.put(1)
# q.put('a')
# q.put((1,2,3))
# q.put(({'k':'v'}))
# print(q.qsize())
# print('q : ',q)
# print('get : ',q.get())
# print(q.qsize())

deque 双端队列

# from collections import deque
# dq = deque()
# dq.append(2)
# dq.append(5)
# dq.appendleft('a')
# dq.appendleft('b')
# print(dq)
# # print(dq.pop())
# # print(dq)
# # print(dq.popleft())
# # print(dq)
# print(dq.remove('a'))
# print(dq.insert(2,'123'))
# print(dq)

 在insert remove的时候 deque的平均效率要高于列表
列表根据索引查看某个值的效率要高于deque
append 和pop对于列表的效率是没有影响

 

Counter计数器

1. 对字符串\列表\元祖\字典进行计数,返回一个字典类型的数据,键是元素,值是元素出现的次数

举例:

from collections import Counter
s = "hello-python-hello-world"
a = Counter(s)
print(a)
# 结果 
Counter({'-': 3, 'd': 1, 'e': 2, 'h': 3, 'l': 5, 'n': 1, 'o': 4, 'p': 1, 'r': 1, 't': 1, 'w': 1, 'y': 1})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2. most_common(n) (统计出现最多次数的n个元素)

举例:

print(a.most_common(3))
 # 结果
 [('l', 5), ('o', 4), ('h', 3)] 出现次数最多的三个元素
  • 1
  • 2
  • 3

3. elements (返回一个Counter计数后的各个元素的迭代器)

举例:

for i in a.elements():
    print(i, end="")
# 结果:
hhheellllloooo---pytnwrd
  • 1
  • 2
  • 3
  • 4

4. update (类似集合的update,进行更新)

举例:

a.update("hello123121")
print(a)
# 结果: 
Counter({'-': 3, '1': 3, '2': 2, '3': 1, 'd': 1, 'e': 3, 'h': 4, 'l': 7, 'n': 1, 'o': 5, 'p': 1, 'r': 1, 't': 1, 'w': 1, 'y': 1})
  • 1
  • 2
  • 3

5. subtract (类似update,做减法)

s1 = "abcd"
s2 = "cdef"
a1 = Counter(s1)
a2 = Counter(s2)
a1.subtract(a2)
print(a1)
# 结果: 
Counter({'a': 1, 'b': 1, 'c': 0, 'd': 0, 'e': -1, 'f': -1
posted @ 2020-11-03 13:25  断浪狂刀忆年少  阅读(244)  评论(0编辑  收藏  举报