Python 常用模块简析
-
reandom:随机数获取
-
random.random():获取[0.0,1.0)之间内的随机浮点数。
print(random.random()) # 不包含1,取不到1.0
-
random.randint(a,b):获取指定[a,b]区间内的随机整数。
print(random.randint(3, 5)) # 随机获取3到5之间的整数,可以取到3和5
-
random.uniform(a,b):获取[a,b)范围内的随机浮点数。
print(random.uniform(3, 5)) # 随机获取3到5(不包含5)之间的随机浮点数
-
random.shuffle(x):混洗,把参数所包含的元素进行打乱,x必须为可变数据类型。
list1 = list(range(10)) random.shuffle(list1) print(list1)
-
random.sample(x,k):随机取样,从x中随机抽取k个数据,组成一个列表返回。
-
random.choice(x):从x(元组或列表)中随机抽取一个元素
# tuple元组是不可变数据类型,可以通过random.sample()函数实现打乱顺序 tup = tuple(range(10)) print(random.choice(tup)) # 从tup中随机抽取一个元素返回 lst = random.sample(tup, len(tup)) # 从tup中提取全部元素进行随机排序,返回一个列表 print(lst) # 此功能一般用于在某个序列内随机取样。
-
random.choices(population,weights=None,*,cum_weights=None,k=1):从指定序列中随机抽取k次数据,返回一个列表,可以设置权重
- population:集群。
- weights:相对权重。
- cum_weights:累加权重。
- k:选取次数。
注意:每次选取都不会影响原序列,每一次选取都是基于原序列
import random a = [1,2,3,4,5] print(random.choices(a,k=6)) 解析:重复6次从列表a中的各个成员中选取一个数输出,各个成员出现概率基本持平。 结果:[5, 4, 5, 4, 1, 3](随机生成的) print(random.choices(a,weights=[0,0,1,0,0],k=6)) 解析:重复6次从列表a中提取3,最终得到[3, 3, 3, 3, 3, 3] 结果:[3, 3, 3, 3, 3, 3](固定结果) print(random.choices(a,weights=[1,1,1,1,1],k=6)) 解析:重复6次从列表a中的各个成员中选取一个数输出,各个成员出现概率基本持平。 结果:[5, 4, 3, 5, 4, 3](随机生成的) print(random.choices(a,cum_weights=[1,1,1,1,1],k=6)) 结果:[1, 1, 1, 1, 1, 1](固定结果)
参数weights设置相对权重,它的值是一个列表,设置之后,每一个成员被抽取到的概率就被确定了。 比如weights=[1,2,3,4,5],那么第一个成员的概率就是P=1/(1+2+3+4+5)=1/15。 cum_weights设置累加权重,Python会自动把相对权重转换为累加权重,即如果你直接给出累加权重,那么就不需要给出相对权重,且Python省略了一步执行。 比如weights=[1,2,3,4],那么cum_weights=[1,3,6,10] 这也就不难理解为什么cum_weights=[1,1,1,1,1]输出全是第一个成员1了。
-
-
time:和时间相关
这个模块封装了获取时间戳和字符串形式时间的一些方法。
-
时间戳:从时间元年(1970年1月1日0点0分0秒)到现在经过的秒数。
print(time.time())
-
获取结构化时间对象:time.gmtime() 默认参数是当前系统时间的时间戳
print(time.gmtime()) # 当前系统时间的格林尼治时间戳 >>>time.struct_time(tm_year=2020, tm_mon=12, tm_mday=4, tm_hour=8, tm_min=35, tm_sec=17, tm_wday=4, tm_yday=339, tm_isdst=0) print(time.gmtime(1)) # 获取时间元年后1秒的时间戳 >>>time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=1, tm_wday=3, tm_yday=1, tm_isdst=0)
-
获取结构化本地时间对象:time.localtime()
用法与gmtime()方法一样,但获取得到的是当前时区的时间戳。
-
格式化时间对象和字符串之间的转换:
把格式化时间对象转换成字符串:time.strftime(字符串格式,时间戳)
s = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) # 不能有中文字符,否则报错 print(s) >>>2020-12-04 17:11:23
-
把时间字符串转换成格式化时间对象:time.strptime(字符串,时间格式)
time_obj=time.strptime('2020 09 10','%Y %m %d') print( time_obj) >>>time.struct_time(tm_year=2020, tm_mon=9, tm_mday=10, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=254, tm_isdst=-1)
时间日期格式化符号 %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.的等价符 %w 星期(0-6),星期天为星期的开始 %U 一年中的星期数(00-53)星期天为星期的开始 %W 一年中的星期数(00-53)星期一为星期的开始 %Z 当前时区的名称 %% %号本身 -
格式化时间对象(time.struct_time)==>时间戳:time.mktime(时间对象)
print(time.mktime(time.localtime())) >>>1607081631.0
-
暂停当前线程,睡眠x秒
time.sleep(秒数)
-
-
datetime:日期和时间模块
封装了一些和日期、时间相关的类,datetime中的类主要是用于数学计算的。
-
date类:包含有年月日属性
import datetime d=datetime.date(2020,12,5) print(f'{d.year}年{d.month}月{d.day}日') >>>2020年12月5日
-
time类:包含时分秒属性
t = datetime.time(18, 35, 59) print(f'{t.hour}点{t.minute}分{t.second}秒') >>>18点35分59秒
-
datetime类:包含年月日时分秒属性
dt=datetime.datetime.now() print(dt) print(f'现在是{dt.year}年{dt.month}月{dt.day}日,{dt.hour}时{dt.minute}分{dt.second}秒{dt.microsecond}微秒') >>>2020-12-05 16:35:41.396585 >>>现在是2020年12月5日,16时35分41秒396585微秒
-
timedelta类:时间的变化量,运算对象可以有date、datetime、timedelta
t = datetime.datetime(2020, 10, 31, 14, 5, 59) # 设定时间为2020.10.31,14:05:59 td = datetime.timedelta(days=1, seconds=1) # 时间变化量为1天零秒 print(t + td) # 进行运算之后会将变化量体现出来 >>>2020-11-01 14:06:00
例:计算某一年的2月份有几天。
普通算法:根据年份计算是否闰年,再得出2月份天数;
使用timedelta模块,首先创建出指定年份的3月1日,然后让它倒退1天,即可以得出2月最后一天日期。
year = int(input('请输入年份:')) d = datetime.date(year, 3, 1) td = datetime.timedelta(days=1) print((d-td).day)
和时间段timedelta类进行运算之后,结果的类型如何判断:
运算结果类型 ==> 运算时第一个操作数的类型一致。
-
-
os、sys
-
os模块:和操作系统相关的操作被封装到这个模块中。
-
和文件操作相关:重命名,删除
os.rename('a.txt','b.txt)
,对a.txt文件进行重命名os.remove('a.txt')
,对a.txt文件进行删除 -
对目录进行操作:删除空目录
os.removedirs('aa')
:删除aa目录 -
获取当前工作目录路径
os.getcwd()
:返回一个当前目录字符串 -
获取当前(指定)目录下所有文件和子目录列表
os.listdir(路径)
:默认返回当前工作目录下所有文件和子目录名的列表,也可以指定路径 -
附带内容:删除有内容的目录,删除目录树,需要shutil模块支持
import shutil shutil.rmtree('aa') # 直接删除整个aa目录
-
os.path
模块:和路径相关的操作方法-
os.path.dirname
:获取指定文件或路径的父目录(指定路径不需要真实存在)path = os.path.dirname(r'c:windowssystem32host') print(path) >>>c:windowssystem32
-
os.path.basename
:获取指定路径文件名(指定路径不需要真实存在)filename = os.path.basename(r'c:windowssystem32fontsxxx.font') print(filename) >>>xxx.font
-
os.path.split(r'd:/aaa/bbb/ccc/a.txt')
:将指定路径中的路径和文件名切分开,返回一个元组。 -
os.path.join('d:\','aaa','bbb','ccc','a.txt')
:将指定字符串拼接成一个完整的路径地址。 -
os.path.abspath('.aaa/bbb/ccc/a.txt')
:反回当前工作目录下指定路径的绝对路径 -
os.path.isabs('a.txt')
:判断是否绝对路径 -
os.path.isdir('aaa.jpg')
:判断对象是否为目录,文件不存在为False -
os.path.isfile('d:\backup.cdr')
:判断对象是否为文件,文件不存在为False -
os.path.exists('c:/autoexec.bat')
:判断文件是存存在。
-
-
-
sys模块:和python解释器相关的操作
-
获取命令行方式运行的脚本后面的参数,sys.argv[0]为该脚本绝对路径和文件名。
import sys arg1=int(sys.argv[1]) arg2=int(sys.argv[2]) print(arg1+arg2) ---------终端脚本方式运行以上程序----------- G:python>python os_sys_demo.py 2 8 10
-
sys.path
:返回当前系统中解释器注册的路径 ,可以通过PYTHONPATH来进行初始化。由于是在程序执行的时候进行初始化的,所以,路径的第一项path[0]始终是调用解释器脚本所在的路径。如果是动态调用的脚本,或者是从标准输入读取到脚本命令,则path[0]是一个空字符串。程序中可以随时对这个路径进行修改,以达到动态添加模块路径的目的。
-
sys.modules
:返回系统已经加载的模块,以字典形式返回。对这个字典中的值进行修改并没有什么具体意义,反而有时会引发异常。
常用来作为是否重新加载一个模块的判断依据。
-
-
-
json模块:将数据转换成字符串,用于存储或网络传输。
JavaScript Object Notation:java脚本对象标记(描述)语言,它将所有的内容都转换成字符串,目前已经成为了简单的数据交换格式。
Python中除了“集合”类型无法转换之外,其他都支持。
-
serialization:序列化,将内存中的数据,转换成字节串用以保存在文件或者通过网络传输,这称为序列化过程。
-
json.dumps(obj)
:将数据对象进行序列化,元组可以被json序列化,但是经过json序列化之后会变成列表。list1 = json.dumps([1, 2, 3]) print(list1, type(list1)) tuple1 = json.dumps((44, 33, 22)) # 元组被序列化之后会变成列表 print(tuple1, type(tuple1)) dict1 = json.dumps({'name': 'amwkvi', 'age': 18}) print(dict1, type(dict1)) >>>[1, 2, 3] <class 'str'> [44, 33, 22] <class 'str'> {"name": "amwkvi", "age": 18} <class 'str'>
-
json.dump(obj,文件句柄)
:json模块直接操作文件句柄,该方法操作对象为文件,将数据对象序列化之后写进文件。with open('a.txt', mode='at', encoding='utf-8') as f: json.dump(['abc', 112233, True, 3.23], f) json.dump(list1, f) -----------运行结果:创建一个a.txt文件,内容为以下--------------- ["abc", 112233, true, 3.23]"[1, 2, 3]"
-
-
deserialization:反序列化,将文件中或网络中接收到的数据转换成内存中原来的数据类型,这称为反序列化过程。
-
json.loads(obj)
:将数据对象进行反序列化,将json字符串反序列化为原数据类型。list2=json.loads(list1) print(list2,type(list2)) tuple2=tuple(json.loads(tuple1)) print(tuple2,type(tuple2)) dict2=json.loads(dict1) print(dict2,type(dict2)) >>>[1, 2, 3] <class 'list'> (44, 33, 22) <class 'tuple'> {'name': 'amwkvi', 'age': 18} <class 'dict'>
-
json.load(obj,文件句柄)
:操作对象为文件,将从文件中读取出来的内容反序列化成相应的数据格式。with open('a.txt', encoding='utf-8') as f1: res = json.load(f1) print(res, type(res)) >>>['abc', 112233, True, 3.23] <class 'list'>
-
-
jons文件通常是一次性写,一次性读,使用另外的方法可以实现多次写,多次读。
以上例子中对文件的操作时,一次性读取多个数据会出错,所以一般还是用dumps和loads配合文件句柄对文件按行或者数据段进行操作,例:
import json with open('a.txt', mode='wt', encoding='utf-8') as f: f.write(json.dumps(['abc', 112233, True, 3.23]) + ' ') # 按行写入数据 f.write(json.dumps({'name': 'amwkvi', 'age': 18}) + ' ') # 每行后面加换行符 with open('a.txt', encoding='utf-8') as f1: for line in f1: # 用遍历文件句柄的方法对文件内容进行操作 res = json.loads(line.strip()) # 将每一行结尾的换行符去年再进行反序列化 print(res, type(res)) ----------运行结果----------- ['abc', 112233, True, 3.23] <class 'list'> {'name': 'amwkvi', 'age': 18} <class 'dict'>
-
-
pickle模块:将python中所有的数据类型转换成字节串(序列化过程),或将字节串转换成python中的数据类型(反序列化过程)。
-
序列化过程:pickle.dumps()、pickle.dump()
-
反序列化过程:pickle.loads()、pickle.load()
以上方法使用与json没有区别,例:
import pickle bys1 = pickle.dumps((1, 2, 4, 'abc')) tup1 = pickle.loads(bys1) print(tup1, type(tup1)) >>>(1, 2, 4, 'abc') <class 'tuple'> # pickle支持元组 bys2 = pickle.dumps(set('aaaaamwkvi')) set1 = pickle.loads(bys2) print(set1, type(set1)) >>>{'a', 'w', 'k', 'v', 'i', 'm'} <class 'set'> # pickle支持集合
-
pickle.dump()和pickle.load()对于文件的操作方法也是和json一样,和json区别是可以多次写入多次读取。但是在实际应用当中,还是只会用到一次写入一次读取而已,因为并不知道前面写入了几次。
with open('a.txt',mode='wb') as f:
,操作文件时候mode需要用b类型,因为pickle序列化结果是字节。
-
-
json和pickle的特点与区别:
-
json:
- 不是所有的数据类型都可以转化,转化结果是字符串。
- json.dump()和json.load()不能多次对同一个文件序列化。
- json转化的数据可以跨语言。
-
pickle:
- 所有的python类型都能序列化,转化结果是字节串。
- pickle.dump()和pickle.load()可以多次对同一个文件序列化。
- pickle转化的数据不可以跨语言。
-
-
hashlib模块:
这里面封装了一些用于加密的类。
加密的目的:用于判断和验证,而并非解密。
- 案例:验证用户名的密码是否匹配,但存于数据库中的密码又不可以明文保存;
- 验证:给第一次创建的密码数据加密,用一另个数据加密的结果和第一个加密结果对比,如果结果相同,说明密码原文相同,如果不同,说明密码原文不同。
特点:
- 把一个很大的数据,切分成不同的小块,分别对不同的块进行加密,再汇总的结果,和直接对整体数据进行加密的的结果是一致的。
- 单向加密,不可逆。
- 原始数据的一点小变化,将导致结果的非常大的差异,“雪崩”效应。
加密算法的使用步骤:
- 获取一个加密方法(md5/sha1/shake等);
- 调用该算法的update()方法对对象进行加密,update方法可以调用多次;
- 调用该算法的hexdigest()方法获取加密后的结果,或digest()方法获取字节串的加密结果。
举例:
import hashlib m = hashlib.md5() # 获取一个加密对象 m.update(b'abc') # 加密对象需要以字节形式导入 res = m.hexdigest() # 获取加密的结果 print(res) # 加密的结果是字符串 m.update('abc中文'.encode('utf-8')) # 加密对象中如果有中文字符,需要转化为字节类型 res = m.hexdigest() print(res) >>> 900150983cd24fb0d6963f7d28e17f72 bb33ac3c7ccefffd55fabfd949dd8d49
-
不同加密算法的最明显区别在于加密后结果的长度不同,长度越长,加密过程耗时越长。
-
使用加密算法时,可以在创建加密对象步骤中直接将对象进行加密,而不通过update方法,最终结果是一致的。
m = hashlib.md5() m.update(b'abc') m.update(b'def') print(m.hexdigest()) m = hashlib.md5(b'abcdef') # 在创建加密方法的时候直接进行加密 print(m.hexdigest()) # 直接获取加密结果 >>>e80b5017098950fc58aad83c8c14978e e80b5017098950fc58aad83c8c14978e # 两次加密结果相同
-
collections模块:
这里面包含一些可以自定义的“容器”类数据。
-
namedtuple():命名元组,定义一个tuple的子类。
可以使用这个方法定义一个自己的类,类的结构和说明都可以自己写,自定义的类等同于“int、str、list、dict”等结构体。
自定义的类名,建议使用首字母大写形式,便于区分系统内置的一些模块名。自定义类的元素可以通过属性直接访问,也可以通过索引方式访问
from collections import namedtuple Rectangle = namedtuple('这是一个描述长方形长和宽的类', ['length', 'width']) f = Rectangle(12, 4) print(type(Rectangle)) # <class 'type'> print(type(f)) # <class '__main__.这是一个描述长方形长和宽的类'> print(f.length,f.width) # 12 4 # 通过属性访问 print(f[0],f[1]) # 12 4 # 通过索引访问
-
defaultdict():默认值字典,在读取不存在键的时候,会根据定义的“工厂方法”给这个不存在的键匹配一个默认值,并将这个不存在的键加入到字典中。
from collections import defaultdict mydict=defaultdict(int,name='amwkvi',age=18) print(mydict) # defaultdict(<class 'int'>, {'name': 'amwkvi', 'age': 18}) print(mydict['car']) # 0 # 在此工厂方法为int函数,所以直接取第一个值 print(mydict) # defaultdict(<function f at 0x0000026332421C18>, {'name': 'amwkvi', 'age': 18})
工厂方法也可以使用自定义函数,但是需要注意自定义函数不能有参数,它的返回值即defaultdict的默认值。
def f(): # 自定义一个没有参数的函数 return 'Yamaha' # 这个返回值即默认值字典的默认值 myd = defaultdict(f, name='amwkvi', age=18) print(myd) # defaultdict(<function f at 0x00000231EFF81C18>, {'name': 'amwkvi', 'age': 18}) print(myd['car']) # Yamaha print(myd) # defaultdict(<function f at 0x00000231EFF81C18>, {'name': 'amwkvi', 'age': 18, 'car': 'Yamaha'})
-
Counter():计数器
from collections import Counter count = Counter('adssddaaaaa') # 定义统计对象 print(count) # 显示统计结果:Counter({'a': 6, 'd': 3, 's': 2}) print(count.most_common(2)) # 显示统计结果的前2名: [('a', 6), ('d', 3)] print(sorted(count.elements())) # 将统计结果进行转为可迭代对象,再排序输出:['a', 'a', 'a', 'a', 'a', 'a', 'd', 'd', 'd', 's', 's']
-