Python学习之常用内置模块
- os 模块
- os的文件操作
- remove()
- rename()
- rmdir()
- removedirs()
- rmtree()
- os的路径操作
- dirname()
- basename()
- split()
- splitext()
- isdir()
- isfile()
- islink()
- exists()
- sys 模块
- argv()
- exit()
- getwindowsversion()
- path()
- paltform属性
- time 模块
- gmtime()
- localtime()
- strftime()
- strptime()
- datetime模块
- date类
- 语法:
- 常用函数:
- time类
- 语法:
- 常用函数:
- datetime类
- 语法:
- timedelta类
- random模块
- random模块常用方法有:
- random.random()
- random.randint(a, b)
- random.uniform(a, b)
- random.shuffle()
- random.smaple(iter, x)
- random.randrange()
- json模块和pickle模块
- json模块
- dumps()
- loads()
- dump 和load
- pickle模块
- hashlib模块
- collections模块
- Counter类
- namedtuple类
- defaultdict类
os 模块
os的文件操作
remove()
remove是删除文件的命令,需要一个参数,如果传入的是一个路径,报 IsADirectoryError
错误
语法:
remove(file_path)
例1:
import os
os.remove('/tmp/a.txt')
# 文件不存在时报错
Traceback (most recent call last):
File “/root/project_file/demo.py”, line 3, in
os.remove(’/tmp/a.txt’)
FileNotFoundError: [Errno 2] No such file or directory: ‘/tmp/a.txt’
rename()
rename既能修改文件名,也能修改目录名,需要两个参数,第一个是原文件名,第二个是目标文件名。 修改文件名不会改变文件中的内容。
语法:
rename(src, dst)
注意:
如果目标文件名存在:
在Linux系统中,会直接覆盖。报 OSError
(目标文件存在时) 或 FileExistsError
(源文件不存在时)错误
例1:
# 创建文件和目录
mkdir -p /tmp/dir1/dir2 # 创建目录
touch /tmp/dir1/a.txt # 创建文件
echo "This is a test file in old_file named a.txt" >> /tmp/dir1/a.txt # 向文件写入内容
结果是:
/tmp
└── dir1
├── a.txt
└── dir2
import os
os.rename('/tmp/dir1', '/tmp/dir') # 给目录改名
os.rename('/tmp/dir/a.txt', '/tmp/dir/test.txt') # 在改名后的目录中修改文件名
运行结果:
/tmp
└── dir
├── dir2
└── test.txt
rmdir()
rmdir是删除目录,如果目录不为空,将报 OSError
(非空报错)或 FileNotFoundError
(不存在报错)错误
语法:
rmdir(path)
例1:
创建目录
mkdir /tmp/dir1 # 创建目录
touch /tmp/dir1/a.txt # 目录中创建文件,使目录不为空
tree # tree查看结果,返回树状结构
/tmp
└── dir1
└── a.txt
import os
os.rmdir('/tmp/dir1')
运行结果:
Traceback (most recent call last):
File “/projects/oldboy/laptop/day09/test_file.py”, line 6, in
os.rmdir(’/tmp/dir1’)
OSError: [Errno 39] Directory not empty: ‘/tmp/dir1’
removedirs()
removedirs也是删除目录,跟rmdir的区别是,如果层级目录都是空,removedirs会逐层删除空目录。
语法:
removedirs(path)
例1:
# 创建目录结构
mkdir -p /tmp/dir1/dir2/dir3/dir4
touch /tmp/dir1/dir2/a.txt
tree # 用tree查看结果
结果如下:
/tmp
└── dir1
└── dir2
├── a.txt
└── dir3
└── dir4
import os
os.removedirs('/tmp/dir1/dir2/dir3/dir4')
运行结果:
└── dir1
└── dir2
└── a.txt
说明:
由于dir4删除后dir3也是一个空目录,removedirs会继续删除空目录,直到dir2,里面有个a.txt目录不为空,如果dir2也是空,会继续删除下去。而rmdir只会删除dir4,这是removedirs和rmdir最明显的区别
rmtree()
上面两个删除目录的方法,无法删除非空目录。rmtree方法可以删除非空目录,这个方法位于 shutil
模块中,要使用该方法需要先导入模块
语法:
rmtree(path)
例1:
mkdir -p /tmp/dir1/dir2/dir3/dir4
touch /tmp/dir1/dir2/dir3/dir4/a.txt
tree # 用tree查看结果
运行结果:
/tmp/
└── dir1
└── dir2
└── dir3
└── dir4
└── a.txt
import os
import shutil
# os.rmdir('/tmp/dir1/dir2') # 报错:OSError
shutil.rmtree('/tmp/dir1/dir2') # 正常删除
运行结果:
/tmp/
└── dir1
os的路径操作
os的路径操作在子模块中,即os.path模块中
dirname()
dirname返回传入的path中的路径名,并不会验证路径和文件是否存在
例1:
import os
ret = os.path.dirname('/tmp/dir1/dir2/a.txt')
print(ret)
运行结果:
/tmp/dir1/dir2
basename()
basename 返回给定路径中的文件名,同dirname一样,也不会考虑文件或路径是否存在,只管返回文件名,如果路径以斜线结尾,那么将返回空
例1:
import os
ret = os.path.basename('/tmp/dir1/dir2/a.txt')
print(ret)
运行结果:
a.txt
split()
split 以元组的形式返回路径名和文件名,不考虑路径是否有效
例1:
import os
ret = os.path.split('/tmp/dir1/dir2/a.txt')
print(ret)
运行结果:
(’/tmp/dir1/dir2’, ‘a.txt’)
splitext()
splittext 同split一样也是返回一个元组,区别在于,splittext 返回的元组中以英文的句号为分隔,相当于返回的是文件的后缀名。句点搜索从右往左,如果没有返回空
例1:
import os
my_path = '/tmp/dir1/dir2/a.txt'
ret = os.path.split(my_path)
print('split返回:', ret)
ret1 = os.path.splitext(my_path)
print('splitext返回', ret1)
运行结果:
split返回: (’/tmp/dir1/dir2’, ‘a.txt’)
splitext返回 (’/tmp/dir1/dir2/a’, ‘.txt’) # 返回的相当于是后缀名
isdir()
isdir判断给出的路径是不是目录,只有路径真实存在并且是目录的时候才返回True,否则都是False,如果是软连接,该软连接指向的也是目录,返回的结果也是True
例1:
mkdir /tmp/dir1 # 创建目录
touch /tmp/dir1/a.txt # 创建文件
ln -s /tmp/dir1 /test # 创建软连接
import os
mypath = '/tmp/dir1/a.txt' # 不是目录是一个文件的路径
ret = os.path.isdir(mypath)
print(ret)
mypath2 = '/test'
ret2 = os.path.isdir(mypath2)
print(ret2)
运行结果:
Fasle
True
isfile()
判断给出的路径是不是一个文件
例1:
import os
print(os.path.isfile('/root'))
print(os.path.isfile('/root/project_file/demo.py'))
运行结果:
False
True
islink()
判断给出的路径是不是一个软连接
import os
print(os.path.islink('/root/mnt')) # 将/mnt目录软连接到/root/mnt下
print(os.path.islink('/root/test-hard')) # 先touch一个文件,然后创建一个硬链接
运行结果:
True
False
exists()
判断一个文件或目录是否存在,存在返回True,否则返回False
import os
mypath = '/tmp/dir1/a.txt'
ret = os.path.exists(mypath)
print(ret)
运行结果:
True
sys 模块
argv()
argv是一个列表,该列表存储的是从命令行指向代码时传入的参数, 第一个参数默认是文件名。
例1:
import sys
for idx, value in enumerate(sys.argv):
print(f'第 { idx } 个参数是:{value}')
运行方式:
python3 /projects/sysdemo.py 你好 数学 英语
运行结果:
第 0 个参数是:/projects/sysdemo.py
第 1 个参数是:你好
第 2 个参数是:数学
第 3 个参数是:英语
exit()
exit 是一个退出函数,他有一个参数 status
指明是按照什么状态退出的,默认是None 他跟 0 是一个意思,说明是正常退出的,status的取值范围是 0 - 127,这个退出状态在Linux中表现为 echo $?
显示的状态码,有时候可以帮助我们查找异常退出的情况
例1:
import sys
try:
num = int(input('请输入一个整数:'))
except ValueError:
# 我们定义数据转换异常就抛出错误代码为 15
sys.exit(15)
运行方式:
python3 /projects/sysdemo.py
请输入一个整数: a # 提示我们输入整数,但我们输入了一个字母
echo $? # $? 打印出退出码
运行结果:
15
getwindowsversion()
获取Windows系统的版本信息, 仅支持在Windows系统上运行 ,他的返回值是一个列表
例1:
import sys
print(sys.getwindowsversion())
path()
path是Python解释器的查找路径,他是一个列表,Python解释器会在列表中的目录下去查找相应的模块信息,如果我们有自定义的模块路径,可以通过append加入该列表
例1:
import sys
print(sys.path)
paltform属性
这是一个属性,不是方法,我们可以通过他获取当前程序运行的平台,然后我们可以针对不同的平台运行对应的程序
对应平台如下:
平台 | 对应代码 |
AIX | 'aix' |
Linux | 'linux' |
Windows | 'win32' |
Windows/Cygwin | 'cygwin' |
macOS | 'darwin' |
例1:
import sys
ret = sys.platform
if ret.startswith('linux'):
print('这是Linux平台')
elif ret.startswith('win32'):
print('这是Windows平台')
在Linux下运行的结果:
这是Linux平台
在Windows下运行的结果:
这是Windows平台
time 模块
time提供了与时间相关的一些函数
time模块常用的方法有:
time()
time()返回从 1970-01-01 00:00:00
秒到当前时间经过的秒数
例1:
import time
ret = time.time()
print(ret)
运行结果:
1596771508.143643
gmtime()
该方法有一个参数,输入相应的描述,会给出具体的时间对象
gmtime() 返回格林尼治时间,该方法返回的是一个time类型的结构化时间对象,我们可以使用下标或者属性名将值取出来
下标 | 属性名 | 说 明 | 值范围 |
0 | tm_year | 年份 | 2020 |
1 | tm_mon | 月份 | 1-12 |
2 | tm_mday | 日 | 1-31 |
3 | tm_hour | 时 | 0-23 |
4 | tm_min | 分 | 0-59 |
5 | tm_sec | 秒 | 0-61,因为涉及到闰秒,可查看文档 |
6 | tm_wday | 星期几 | 0-6,周一是0 |
7 | tm_yday | 一年中的第几天 | 0-366 |
8 | tm_isdst | 夏令时 | 0,1或-1,夏令时为1, 否则为0,-1表示未知 |
无索引 | tm_zone | 时区名缩写 | / |
无索引 | tm_gmtoff | 以秒为单位向UTC东时区偏移 | / |
例1:
import time
ret = time.gmtime()
print(ret)
print(type(ret))
print('年份是:', ret[0]) # 下标方式取年份
print('月份是:', ret.tm_mon) # 属性方式取月份
运行结果:
time.struct_time(tm_year=2020, tm_mon=8, tm_mday=7, tm_hour=3, tm_min=51, tm_sec=24, tm_wday=4, tm_yday=220, tm_isdst=0)
<class ‘time.struct_time’>
年份是: 2020
月份是: 8
例2:
import time
ret = time.gmtime(1297879384)
print(ret)
print(f'给定的秒数是:{ret.tm_year} 年 {ret.tm_mon} 月 {ret.tm_mday} 日 '
f'{ret.tm_hour}:{ret.tm_min}:{ret.tm_sec} 星期{ret.tm_wday + 1}')
运行结果:
time.struct_time(tm_year=2011, tm_mon=2, tm_mday=16, tm_hour=18, tm_min=3, tm_sec=4, tm_wday=2, tm_yday=47, tm_isdst=0)
给定的秒数是:2011年 2 月 16 日 18:3:4 星期3
localtime()
该方法有一个参数,输入相应的描述,会给出具体的时间对象
获取本地时间,用法跟gmtime()一样,只是 时
用的是本地时区
import time
ret = time.localtime() # 中国是东八区,用gmtime() hour 需要加8,localtime不需要
print(ret)
print(type(ret))
print('年份是:', ret[0]) # 下标方式取年份
print('月份是:', ret.tm_mon) # 属性方式取月份
运行结果:
time.struct_time(tm_year=2020, tm_mon=8, tm_mday=7, tm_hour=12, tm_min=10, tm_sec=26, tm_wday=4, tm_yday=220, tm_isdst=0)
<class ‘time.struct_time’>
年份是: 2020
月份是: 8
strftime()
strftime()是格式化时间戳,将时间戳转换成易读的格式
语法:
strftime(格式 [, 时间对象])
注意:
时间对象可选,如果时间对象没有,默认是 localtime() 获取的时间戳
占位符 | 说明 |
%a | 当前地区的星期缩写 |
%A | 当前地区的星期全称 |
%b | 当前地区月份的缩写 |
%B | 当前地区月份的全称 |
%p | 12小时制,大写方式显示上午(AM),下午(PM) |
%U | 显示当前为一年中的第几周,以星期天为每周的第一天 |
%W | 显示当前为一年中的第几周,以星期一为每周的第一天 |
%w | 以数字的形式显示,星期中的第几天(0-6,星期天是0) |
%y | 年:两位数的方式表示年份 |
%Y | 年:完整的四位数表示年份 |
%m | 月:以两位数显示 |
%d | 日:以两位数显示 |
%H | 时:24小时制,以两位数显示 |
%I | 时:12小时制,以两位数显示 |
%M | 分:以两位数显示 |
%S | 秒:以两位数显示 |
%z | 显示当前的时区(东八区:+0800) |
%% | 显示一个百分号,转义 |
例1:
import time
ret = time.strftime('%Y-%m-%d %H:%M:%S')
print(ret)
运行结果:
2020-08-07 13:49:21
strptime()
将易读的时间,解析成时间对象,时间字符串和格式化的格式必须完全一致,否则会报 ValueError
错误
语法:
strptime(时间字符串, 格式)
例1:
import time
time_str = '2020-08-07 14:52:32'
# time_str = '2020/08/07 14:52:32' 报错,因为年月日的分隔符不匹配
ret = time.strptime(time_str, '%Y-%m-%d %H:%M:%S') # 格式必须跟time_str中的格式和分隔符一样
print(ret)
运行结果:
time.struct_time(tm_year=2020, tm_mon=8, tm_mday=7, tm_hour=14, tm_min=52, tm_sec=32, tm_wday=4, tm_yday=220, tm_isdst=-1)
datetime模块
date类
date类中是日期相关的内容,date类只处理年月日
该类需要三个初始化参数 year, month, day
语法:
datetime.date(year, month, day)
说明:
三个参数的取值范围如下,如果有一个超出了范围,报 ValueError
错误
1 <= year <= 9999
1 <= month <=12
1<= day <= 给定月份在年份中的天数
例1:
import datetime
ret = datetime.date(2020, 8, 7)
print(ret)
运行结果:
2020-08-07
常用函数:
方法 | 说明 |
方法 | |
today() | 获取当前日期 |
fromtimestamp(timestamp) | 将时间戳转换成日期 |
fromordinal(days) | 返回给定天数是从1年1月1日经过days天的日期,它和 toordinal 函数正好相反 |
toordinal() | 将一个日期转换成从1年1月1日开始的天数,它和 fromordinal 函数正好相反 |
fromisoformat(date_string) | 将一个给定的字符串格式的日期,转换成日期对象,字符串格式必须是:YYYY-mm-dd, 3.7版本及以上才支持 |
fromisocalendar(year, week, day) | 给一个日历的,年,周和天,返回该位置的日期, 周[1-53],天[1-7], 3.8版本及以上才支持 |
属性 | |
year | 获取date对象中的年 |
month | 获取date对象中的月 |
day | 获取date对象中的日 |
resolution | 跟datedelta计算的最小单位即:days=1 |
例2:
import datetime
print('today方法:', datetime.date.today())
print('fromtimestamp方法:', datetime.date.fromtimestamp(1596788844))
print('toordinal方法:', datetime.date.toordinal(datetime.date.today()))
print('fromordinal方法:', datetime.date.fromordinal(737644))
ret = datetime.date.today()
print('当前年份是:', ret.year)
print('当前月份是:', ret.month)
print('当前日期是:', ret.day)
运行结果:
today方法: 2020-08-07
fromtimestamp方法: 2020-08-07
toordinal方法: 737644
fromordinal方法: 2020-08-07
当前年份是: 2020
当前月份是: 8
当前日期是: 7
time类
time类中是时间,time类中只处理:时、分、秒、微秒、毫秒和时区
语法:
datetim.time(hour, minute, microsecond, tzinfo=None)
说明:
参数的取值范围如下,如果超出了范围,报 ValueError
错误
0 <= hour <= 24
0 <= minute< 60
0 <= minute< 60
0 <= microsecond < 1000000
常用函数:
方法 | 说明 |
isoformat(timespec='auto') | 指定显示的最小单位: 默认是auto,精确到微秒; hours,精确到小时; minutes,精确到分钟; seconds,精确到秒 |
strftime(format_string) | 按给定的格式输出时间 |
例1:
from datetime import time
ret = time(17, 27, 18, 200)
print('时间对象:', ret)
print('时:', ret.hour)
print('分:', ret.minute)
print('秒:', ret.second)
print('微秒:', ret.microsecond)
print('不指定单位:', ret.isoformat()) # 不指定默认是auto,精确到为秒
print('指定最小单位为时:', ret.isoformat(timespec='hours')) # 指定显示最小单位为小时
print('指定显示最小单位为分:', ret.isoformat(timespec='minutes')) # 指定显示最小单位为分钟
print('指定显示最小单位为秒:', ret.isoformat(timespec='seconds')) # 指定显示最小单位为秒
print(ret.strftime('%H 时 %M 分 %S 秒'))
运行结果:
时间对象: 17:27:18.000200
时: 17
分: 27
秒: 18
微秒: 200
不指定单位: 17:27:18.000200
指定最小单位为时: 17
指定显示最小单位为分: 17:27
指定显示最小单位为秒: 17:27:18
17 时 27 分 18 秒
datetime类
datetime类中是日期和时间,相当于整合了date和time
语法:
datetime(year, month, day, hour, minute, second, microsecond)
说明:
参数的取值范围如下:
MINYEAR <= year <= MAXYEAR,
1 <= month <= 12,
1 <= day <= number of days in the given month and year,
0 <= hour < 24,
0 <= minute < 60,
0 <= second < 60,
0 <= microsecond < 1000000,
常用函数:
方法 | 说明 |
today() | 获取当前时间包含时区tzinfo |
now() | 获取当前时间不包含时区 |
fromtimestamp() | 将时间戳转换成日期 |
timestamp() | 将日期转换成时间戳 |
strftime() | 格式化日期 |
strptime() | 解析日期 |
date() | 获取日期 |
time() | 获取时间 |
例1:
from datetime import datetime
print('获取时间', datetime.today())
print('获取时间:', datetime.now())
print('将时间戳转换成日期:', datetime.fromtimestamp(1596788844))
print('将日期转换成时间戳:', datetime.now().timestamp())
print('格式化日期:', datetime.now().strftime('%Y年 %m月 %d日 %H时 %M分 %S秒'))
print('日期解析:', datetime.strptime('2020年 08月 07日 18时 09分 56秒', '%Y年 %m月 %d日 %H时 %M分 %S秒'))
print('获取日期:', datetime.today().date())
print('获取时间:', datetime.today().time().isoformat(timespec='seconds'))
print('返回日期和时间的字符串:', datetime.today().isoformat(sep=' ', timespec='seconds'))
运行结果:
获取时间 2020-08-07 18:10:43.937599
获取时间: 2020-08-07 18:10:43.937662
将时间戳转换成日期: 2020-08-07 16:27:24
将日期转换成时间戳: 1596795043.93768
格式化日期: 2020年 08月 07日 18时 10分 43秒
日期解析: 2020-08-07 18:09:56
获取日期: 2020-08-07
获取时间: 18:10:43
返回日期和时间的字符串: 2020-08-07 18:10:43
timedelta类
timedelta类是一个时间变化量,可以跟一个日期和日期时间对象进行数学计算,从而获得需要的新时间
注意:
timedelta只能和date、datetime、timedelta进行数学计算, 不能和time进行计算
语法:
timedelta(weeks, days, hours, minutes, seconds, microsecons, milliseconds)
说明:
0 <= microseconds < 1000000
0 <= seconds < 3600*24 (the number of seconds in one day)
-999999999 <= days <= 999999999
支持的操作有(详见官方文档):
+、-、*、/、//、%、divmod
例1:
import datetime
mydate = datetime.date.today() # 获取当前日期
delta1 = datetime.timedelta(days=10) # 初始化 timedelta
print('加之前:', mydate)
mydate += delta1
print('加之后:', mydate)
mydatetime = datetime.datetime.now()
delta2 = datetime.timedelta(hours=2, minutes=10) # 初始化 timedelta
print('加之前:', mydatetime)
mydatetime += delta2 # 加10天零8小时10分钟
print('加之前:', mydatetime)
delta3 = delta1 + delta2
print('delta相加:', delta3)
mytime = datetime.datetime.now().time()
# mytime += delta2 # 报错,不支持这样的操作
print('时间是:', mytime)
运行结果:
加之前: 2020-08-07
加之后: 2020-08-17
加之前: 2020-08-07 18:28:54.503255
加之前: 2020-08-07 20:38:54.503255
delta相加: 10 days, 2:10:00
时间是: 18:28:54.503284
random模块
此模块提供了和随机数相关的方法(random是伪随机数)。在模块内部,使用了将方法赋值给了属性的方式,比如:randrange 是一个属性,在模块内部定义了将Random类的方法赋值给了randrange,因此randrange实际指向的是randrange方法。
randrange内部实现如下:
_inst = Random()
randrange = _inst.randrange
random模块常用方法有:
random.random()
获取 [0.0, 1.0) 之间的浮点数
例1:
import random
print(random.random())
运行结果:
0.25784570611056934
random.randint(a, b)
返回一个在 [a, b] 之间的整数N, 包含a 或 b
例1:
import random
print(random.randint(1, 5))
运行结果:
3
random.uniform(a, b)
返回一个 [a,b]或[a,b) 之间的浮点数(a,b大小顺序不限)
例1:
import random
print(random.uniform(10, 5))
运行结果:
6.314250748038026
random.shuffle()
将一个有序的可变数据类型,打乱,无返回值,改变的是可迭代对象本身
例1:
import random
li = list(range(10))
print(li)
random.shuffle(li)
print(li)
运行结果:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[2, 8, 3, 5, 1, 7, 6, 9, 0, 4]
random.smaple(iter, x)
从一个可哈希的序列或集合中,返回长度为x的一个列表,如果x的长度大于序列或集合,会报 ValueError
错误。如果序列中的元素有重复,那么返回的列表中元素也可能会重复
例1:
import random
li = list(range(10))
print(li)
ret = random.sample(li, 5)
print(ret)
运行结果:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[3, 0, 7, 8, 5]
例2:
import random
li = [1, 2, 3, 4, 5, 6, 7, 2, 1, 5, 7] # 元素重复
print(li)
ret = random.sample(li, 5)
print(ret)
运行结果:
[1, 2, 3, 4, 5, 6, 7, 2, 1, 5, 7]
[2, 4, 3, 1, 2] # 2 重复获得
random.randrange()
返回一个指定范围内的随机数,randrange有三个参数,start和step可以省略,start指定随机数的开始,stop指定随机数的结束位置,step指定步长
例1:
import random
ret = random.randrange(1, 101, 2) # 返回奇数的随机数
print('1~100之间的奇数随机数:', ret)
运行结果:
3
json模块和pickle模块
json模块
json是JavaScript Object Notation的缩写,即java脚本兑换标记语言,已经成为一种简单的数据交换格式,在Python中,只有集合(set)不能用json表示
序列化:将内存中的结构化数据,转换成字节传,用以保存在文件或者通过网络传输称为线性化过程
反序列化: 从文件或网络中获取的数据,转换成内存中原来的数据类型称为返序列化过程
json将数据转换成字符串,用于存储或网络传输,由于并未转换成字节串,所以不太彻底
dumps()
dumps是将内存中的结构化数据进行序列号,即将结构化数据转换成字符串,dumps是从内存到内存,而dump是从内存到文件
例1:
import json
li = [1, 2, 3, 4]
ret = json.dumps(li) # dumps将结构化数据转换成字符串
print(type(ret))
print('%r' % ret) # 用原始格式显示
tu = (1, 2, 3, 4)
ret = json.dumps(tu) # 元组转换后变成了列表的格式,圆括号变成了方括号
print(type(ret))
print('%r' % ret) # 用原始格式显示
运行结果:
<class ‘str’>
‘[1, 2, 3, 4]’<class ‘str’>
‘[1, 2, 3, 4]’
loads()
loads是将从文件或网络中获取的数据,转化为结构化数据,即反序列化。loads是从内存到内存,load是从文件到内存
import json
li = [1, 2, 3, 4]
ret = json.dumps(li) # ret是序列化后的字符串
print('dumps的结果是:%r, 类型是:%s' % (ret, type(ret)))
res = json.loads(ret) # 进行反序列号
print('loads的结果是:%r, 类型是:%s' % (res, type(res)))
运行结果:
dumps的结果是:’[1, 2, 3, 4]’, 类型是:<class ‘str’>
loads的结果是:[1, 2, 3, 4], 类型是:<class ‘list’>
dump 和load
dump和load的作用域上面dumps和loads一样,区别在于,dump和load是转换成流,写入文件和从文件中读取json。 dump和load都一次性存储和读取,如果需要多次,直接用文件的write和read模式
例1:
import json
li = [1, 2, 3, 4]
with open('ret.txt', mode='a+', encoding='utf-8') as f:
json.dump(li, f)
# 读取
with open('ret.txt', mode='r', encoding='utf-8') as f:
ret = json.load(f)
print(ret)
运行结果:
[1, 2, 3, 4]
例2:
import json
li = [1, 2, 3, 4]
with open('ret.txt', mode='a+', encoding='utf-8') as f:
f.write(json.dumps(li) + '\n') # 利用write和dumps
# 读取
with open('ret.txt', mode='r', encoding='utf-8') as f:
for i in f.readlines():
ret = json.loads(i.strip()) # 利用read和loads
print(ret)
运行结果:
[1, 2, 3, 4]
[1, 2, 3, 4]
pickle模块
pickle的用法跟json一样,有四个方法dump、dumps、load、loads,它能处理Python中的所有数据类型包括集合set,
将Python中所有的数据类型转换成 字节串
,序列化过程
将字节串转换成Python中数据类型,反序列化过程。
json和pickle 的区别:
- pickle所有类型都可以序列化,结果是字节串
- pickle的dump和load自带多次写和多次读。
- pickle不能跨语言,只能针对Python语言。
- dumps前是什么类型,loads后还是什么类型,类型不变
例1:
import pickle
li = [1, 2, 3, 4]
ret1 = pickle.dumps(li) # 转换成pickle字节串
print('dumps后的类型是:', type(ret1))
print('dumps后的结果是:', ret1)
tu = (1, 2, 3, 4)
ret2 = pickle.dumps(tu) # 转换成pickle字节串
print('dumps后的类型是:', type(ret2))
print('dumps后的结果是:', ret2)
se = {1, 2, 3, 4}
ret3 = pickle.dumps(se) # 转换成pickle字节串
print('dumps后的类型是:', type(ret3))
print('dumps后的结果是:', ret3)
# 反序列化
res1 = pickle.loads(ret1)
res2 = pickle.loads(ret2)
res3 = pickle.loads(ret3)
print('loads后的结果是:', res1)
print('loads后的结果是:', res2)
print('loads后的结果是:', res3)
运行结果:
dumps后的类型是: <class ‘bytes’>
dumps后的结果是: b’\x80\x03]q\x00(K\x01K\x02K\x03K\x04e.’
dumps后的类型是: <class ‘bytes’>
dumps后的结果是: b’\x80\x03(K\x01K\x02K\x03K\x04tq\x00.’
dumps后的类型是: <class ‘bytes’>
dumps后的结果是: b’\x80\x03cbuiltins\nset\nq\x00]q\x01(K\x01K\x02K\x03K\x04e\x85q\x02Rq\x03.’
loads后的结果是: [1, 2, 3, 4]
loads后的结果是: (1, 2, 3, 4)
loads后的结果是: {1, 2, 3, 4}
例2:
import pickle
with open('ret.txt', mode='wb') as f:
se = {1, 2, 3, 4}
tu = (1, 2, 3, 4)
li = [1, 2, 3, 4]
dic = {'1': 1, '2': 2, '3': 3, '4': 4}
pickle.dump(se, f)
pickle.dump(tu, f)
pickle.dump(li, f)
pickle.dump(dic, f)
with open('ret.txt', mode='rb') as r:
res1 = pickle.load(r)
res2 = pickle.load(r)
res3 = pickle.load(r)
res4 = pickle.load(r)
print(res1)
print(res2)
print(res3)
print(res4)
运行结果:
{1, 2, 3, 4}
(1, 2, 3, 4)
[1, 2, 3, 4]
{‘1’: 1, ‘2’: 2, ‘3’: 3, ‘4’: 4}
hashlib模块
hashlib封装了一些用于加密的类,如:md5, sha1, sha512,可用 print(dir(hashlib))
查看所有加密方法
加密的目的:用于判断和验证,而并非解密
特点:
- 把一个大的数据,切分成不同块,分别对不同的块进行加密,再汇总的结果,和直接对整体数据加密的结果是一致的
- 单向加密,不可逆
- 原始数据的一点小的变化,将导致结果的差异非常大
加密分为三个步骤:
- 获取加密对象
- 调用加密对象的update方法,进行加密
- 通过hexdigest方法获取加密结果
不管用那种加密方式,都是上面三个步骤
例1:
import hashlib
# 获取一个md5加密对象
md5_object = hashlib.md5()
# 调用update方法进行加密,参数必须是bytes类型
md5_object.update('md5加密'.encode())
# 利用hexdigest获取加密结果
ret = md5_object.hexdigest()
print('md5加密结果是:', ret)
运行结果:
md5加密结果是: a3c9c2fe682a79e3b1703f001ba245a9
例2:
import hashlib
# 分块加密
md5_object = hashlib.md5()
md5_object.update('我爱'.encode())
md5_object.update('我的祖国'.encode())
ret = md5_object.hexdigest()
print('分块加密结果是:', ret)
# 未分块加密
md5_object2 = hashlib.md5()
md5_object2.update('我爱我的祖国'.encode())
ret2 = md5_object2.hexdigest()
print('未分块加密结果是:', ret2)
运行结果:
分块加密结果是: e83482ae91900eadbc2384fc92ac6c98
未分块加密结果是: e83482ae91900eadbc2384fc92ac6c98
例3:
利用加密实现注册和登录验证
import hashlib
# 注册将用户名和密码写入文件
def regist(username, pwd):
if username != '' and pwd != '':
ret = get_encryption(username, pwd)
with open('pwd.txt', mode='at', encoding='utf-8') as p, open('users.txt', mode='at', encoding='utf-8') as u:
u.write(username + '\n')
p.write(ret + '\n')
return True
else:
return False
# 登录从文件读取用户名和密码并校验
def login(username, pwd):
if username != '' and pwd != '':
with open('pwd.txt', mode='rt', encoding='utf-8') as p, open('users.txt', mode='rt', encoding='utf-8') as u:
# 校验用户名
for name in u.readlines():
# 需要strip清除后面的换行符或空格
if name.strip() == username.strip():
# 校验密码
for passwd in p.readlines():
# 需要strip清除后面的换行符或空格再比较,因为存储的时候加了回车符号
if passwd.strip() == get_encryption(username.strip(), pwd.strip()):
return True
# 如果用户名不对,返回False,不验证密码
else:
return False
# 获取加密密码信息,并返回加密信息
def get_encryption(username, pwd):
m = hashlib.md5()
m.update(username.encode())
m.update(pwd.encode())
return m.hexdigest()
while 1:
op = input("请选择操作(1-注册 2-登录 0-退出) :")
if op == '0':
break
elif op == '1':
username = input('请输入用户名:')
password = input('请输入密 码:')
if regist(username, password):
print('注册成功')
else:
print('用户名密码不能为空!')
elif op == '2':
username = input('请输入用户名:')
password = input('请输入密 码:')
if login(username, password):
print('登录成功')
else:
print('登录失败')
else:
print('输入错误,请重新输入!!!')
collections模块
这个模块提供了抽象基类,可以用来创建一个特定的接口
Counter类
Counter类是dict的一个子类,它的参数是一个可哈希的对象或者一个映射,并返回一个字典,字典的键是可哈希对象的每个元素,值是该键的数量。还有一个most_common()
方法可以获取返回值的前n个
例1:
import collections
ret = collections.Counter('this is a test')
print(ret)
print(ret.most_common(3)) # 获取前三个值
ret2 = collections.Counter(cats=3, dogs=4)
print(ret2)
运行结果:
Counter({‘t’: 3, ‘s’: 3, ’ ': 3, ‘i’: 2, ‘h’: 1, ‘a’: 1, ‘e’: 1}) # 键是字符串中的字符,值是字符的个数统计
[(‘t’, 3), (‘s’, 3), (’ ', 3)]
Counter({‘dogs’: 4, ‘cats’: 3})
namedtuple类
namedtuple类是元组的子类,命名元组对于为csv或sqlite3模块返回的结果元组分配字段名称特别有用
语法:
conllections.namedtuple(‘说明’, [变量1, 变量2])
说明:
-
说明
必须没有空格,可以带下划线 - 变量必须是字符串
例1:
import collections
Point = collections.namedtuple('说明', ['x', 'y'])
p = Point(12, 23)
ret = p.x + p.y
print(ret)
运行结果:
35
defaultdict类
defaultdict是字典dict的一个子类,用法跟字典类似,参数是一个default_factory
语法:
collections.defaultdict([default_factory[, …]])
例1:
s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
d = collections.defaultdict(list)
for k, v in s:
d[k].append(v)
ret = d.items()
print(ret)
print(dict(ret))
运行结果:
dict_items([(‘yellow’, [1, 3]), (‘blue’, [2, 4]), (‘red’, [1])])
{‘yellow’: [1, 3], ‘blue’: [2, 4], ‘red’: [1]}