17Python学习之常用内置模块

常用内置模块

    • os 模块
      • os的文件操作
        • remove()
        • rename()
        • rmdir()
        • removedirs()
        • rmtree()
      • os的路径操作
        • dirname()
        • basename()
        • split()
        • splittext()
        • 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')

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’)

splittext()

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()

判断给出的路径是不是一个文件

islink()

判断给出的路径是不是一个软连接

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)

年份是: 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)

年份是: 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)           # 用原始格式显示

运行结果:


‘[1, 2, 3, 4]’


‘[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]’, 类型是:
loads的结果是:[1, 2, 3, 4], 类型是:

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 的区别:

  1. pickle所有类型都可以序列化,结果是字节串
  2. pickle的dump和load自带多次写和多次读。
  3. pickle不能跨语言,只能针对Python语言。
  4. 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后的类型是:
dumps后的结果是: b’\x80\x03]q\x00(K\x01K\x02K\x03K\x04e.’
dumps后的类型是:
dumps后的结果是: b’\x80\x03(K\x01K\x02K\x03K\x04tq\x00.’
dumps后的类型是:
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)) 查看所有加密方法

加密的目的:用于判断和验证,而并非解密

特点:

  1. 把一个大的数据,切分成不同块,分别对不同的块进行加密,再汇总的结果,和直接对整体数据加密的结果是一致的
  2. 单向加密,不可逆
  3. 原始数据的一点小的变化,将导致结果的差异非常大

加密分为三个步骤:

  1. 获取加密对象
  2. 调用加密对象的update方法,进行加密
  3. 通过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. 说明 必须没有空格,可以带下划线
  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]}

你可能感兴趣的:(102,Python,学习笔记)