第十四章:内置模块(collections、time、datetime、random)
collections 模块
在内置数据类型(dict、list、set、tuple)的基础上,collections 模块还提供了几个额外的数据类型:Counter、deque、defaultdict、namedtuple 和 OrderedDict 等
1.namedtuple: 生成可以使用名字来访问元素内容的 tuple
2.deque: 双端队列,可以快速的从另外一侧追加和推出对象
3.Counter: 计数器,主要用来计数
4.OrderedDict: 有序字典
5.defaultdict: 带有默认值的字典
namedtuple
# 坐标轴的点
Point = namedtuple('point', ['x', 'y', 'z'])
t1 = Point(1,2,3)
t2 = Point(5,2,8)
print(t1.x) # 1
print(t2.z) # 8
print(t1,t2) # point(x=1, y=2, z=3) point(x=5, y=2, z=8)
# 扑克牌的花色与数字
Card = namedtuple('card',['suits','number'])
c = Card('红桃',2)
print(c.suits) # 红桃
print(c.number) # 2
print(c) # card(suits='红桃', number=2)
deque
queue 队列
# 队列 用于 list 很长时,因为删除与插入会变的很慢
import queue
q =queue.Queue() # 创建一个空队列
q.put(2) # 往队列中放值
q.put(5)
q.put(7)
# print(q.qsize()) # 获取数列的大小,在值取完时,大小为 0
print(q.get()) # 从队列中取值,一次只取一个
print(q.get())
print(q.get())
# print(q.get()) # 当去完时,进入阻塞状态
deque 双端队列
# 使用 list 存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,
# 因为 list 是线性存储,数据量大的时候,插入和删除效率很低。
# deque 是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:
from collections import deque
dq = deque([1, 2])
dq.append('a') # 从后面放数据 [1,2,'a']
dq.appendleft('b') # 从前面放数据 ['b',1,2,'a']
dq.insert(2, 3) # ['b',1,3,2,'a']
print(dq.pop()) # a 从后面取数据
print(dq.pop()) # 2 从后面取数据
print(dq.popleft()) # b 从前面取数据
print(dq) # deque([1, 3])
Counter
Counter 类的目的是用来跟踪值出现的次数。
它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为 key,其计数作为 value。
计数值可以是任意的 Interger(包括 0 和负数)。Counter 类和其他语言的 bags 或 multisets 很相似
from collections import Counter
c = Counter('abcdeabcdabcaba')
print(c) #输出:Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1})
# 统计列表中各值出现的次数
from collections import Counter
list = [i for i in 'sfsfsfsag']
print(Counter(list)) # 输出:Counter({'s': 4, 'f': 3, 'a': 1, 'g': 1})
OrderedDict
占内存:列表 < 字典 < 有序字典
注意:Python3.6 之后,字典对哈希表存储作了优化,哈希索引和真正的键值对分开存放。
indices 指向了一列索引,entries 指向了原本的存储哈希表内容的结构。由于 entries 是按照插入顺序进行插入的数组,对字典进行遍历时就能按照插入顺序进行遍历。
from collections import OrderedDict
od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
print(od) # OrderedDict 的 Key 是有序的
print(od['a']) # 1
for k in od:
print(k) # 此时 k 的值就是有序的
# a
# b
# c
defaultdict 默认值的字典
# 有如下值集合 [11,22,33,44,55,66,77,88,99,90...]
# 将所有大于 66 的值保存至字典的第一个 key 中,将小于 66 的值保存至第二个 key 的值中。
from collections import defaultdict
values = [11, 22, 33, 44, 55, 66, 77, 88, 99, 90]
my_dict = defaultdict(list) # 这里可以设置默认为 list,在下面就可以少一层关于是否是列表的判断
for value in values:
if value > 66:
my_dict['k1'].append(value)
else:
my_dict['k2'].append(value)
print(type(my_dict), my_dict)
# <class 'collections.defaultdict'>
# defaultdict(<class 'list'>, {'k2': [11, 22, 33, 44, 55, 66], 'k1': [77, 88, 99, 90]})
time datetime时间模块
time 模块
时间戳是计算机能够识别的时间,时间字符串是人能够看懂的时间,元组则是用来操作时间的。
常用方法
import time
time.sleep(secs) # (线程)推迟指定的时间运行。单位为秒。
time.time() # 获取当前时间戳
表示时间的三种方式
分别为:时间戳、元组(struct_time)、格式化的时间字符串
1、时间戳(timestamp) :通常来说,时间戳表示的是从 1970 年 1 月 1 日 00:00:00 开始按秒计算的偏移量。我们运行 “ type(time.time()) ” ,返回的是 float 类型
2、格式化的时间字符串(Format String):1999-12-06
%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 当前时区的名称
%% %号本身
3、元组(struct_time):struct_time 元组共有9个元素,分别为:(年,月,日,时,分,秒,一年中第几周,一年中第几天,是否是夏令时)
| 索引(Index) | 属性(Attribute) | 值(Values) |
|---|---|---|
| 0 | tm_year(年) | 2011 |
| 1 | tm_mon(月) | 1 - 12 |
| 2 | tm_mday(日) | 1 - 31 |
| 3 | tm_hour(时) | 0 - 23 |
| 4 | tm_min(分) | 0 - 59 |
| 5 | tm_sec(秒) | 0 - 60 |
| 6 | tm_wday(weekday) | 0 - 6(0:周一) |
| 7 | tm_yday(一年中的第几天) | 1 - 366 |
| 8 | tm_isdst(是否是夏令时) | 默认为0 |
三种格式的例子
# 导入时间模块
import time
# 时间戳
t1 = time.time()
print(t1) # 1666198637.8737216
# 时间字符串
t2 = time.strftime("%Y-%m-%d %X")
t3 = time.strftime("%Y-%m-%d %H-%M-%S")
print(t2) # 2022-10-20 00:57:17
print(t3) # 2022-10-20 00-57-17
# 时间元组:localtime将一个时间戳转换为当前时区的struct_time
t4 = time.localtime()
print(t4) # time.struct_time(tm_year=2022, tm_mon=10, tm_mday=20, tm_hour=0, tm_min=58, tm_sec=18, tm_wday=3, tm_yday=293, tm_isdst=0)
格式转换
时间戳和结构化时间
import time
# 时间戳和结构化时间
t = time.time()
print(t)
print(time.localtime(3000000000)) # localtime 时间戳时间 ---> 结构化时间
print(time.gmtime(t))
print(time.mktime(time.localtime())) # 结构化时间 ---> 时间戳时间
格式化时间与结构化时间
print(time.strptime('2000-12.31','%Y-%m.%d')) # 格式化时间 ---> 结构化时间
print(time.strftime('%m/%d/%Y %H:%M:%S',time.localtime(3000000000))) # 结构化时间 ---> 格式化时间
转格式化时间
import time
#结构化时间 --> %a %b %d %H:%M:%S %Y串
#time.asctime (结构化时间) 如果不传参数,直接返回当前时间的格式化串
t1 = time.asctime()
t2 = time.asctime(time.localtime(1500000000))
print(t1) # Thu Oct 20 10:42:51 2022
print(t2) # Fri Jul 14 10:40:00 2017
#时间戳 --> %a %b %d %H:%M:%S %Y串
#time.ctime(时间戳) 如果不传参数,直接返回当前时间的格式化串
t3 = time.ctime()
t4 = time.ctime(1500000000)
print(t3) # Thu Oct 20 10:42:51 2022
print(t4) # Fri Jul 14 10:40:00 2017
datetime 模块
datetime 模块中4 个主要的类:
datetime.time:时间类,只包含时、分、秒、微秒等时间信息。
datetime.date:日期类,只包含年、月、日、星期等日期信息。
datetime.datetime:日期时间类,包含以上两者的全部信息。
datetime.timedelta:时间日期差值类,用来表示两个datetime之间的差值。
常用方法
# 显示当前日期
t = datetime.date.today()
print(t) # 2022-10-20
# 格式化时间 ---> 元组时间
t1 = datetime.date.timetuple(t)
print(t1) # time.struct_time(tm_year=2022, tm_mon=10, tm_mday=20, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=293, tm_isdst=-1)
# 显示当前时间,精确到毫秒
t4 = datetime.datetime.now()
print(t4) # 2022-10-20 08:49:46.349188
# 时间戳时间 ---> 格式化时间
t2 = datetime.date.fromtimestamp(152315464)
print(t2) # 1974-10-30
# 时间戳时间按照自定义格式 ---> 格式化时间
t3 = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print(t3) # 2022-10-20 08:49:46
# 时间的 加减(天、分钟)
t6 = datetime.timedelta(days=3, minutes=60)
t_new = datetime.datetime.now()
print(t_new - t6) # 2022-10-17 07:49:46.349188
# 时区
# 拿到一个时区列表
import pytz
tz = pytz.all_timezones
print(tz) # ['Africa/Abidjan', 'Africa/Accra', 'Africa/Addis_Ababa' ...]
# 时区的时间对比
shanghai = datetime.datetime.now(tz=pytz.timezone("Asia/Shanghai")) # 上海
Eirunepe = datetime.datetime.now(tz=pytz.timezone("America/Eirunepe")) # 爱尔兰
print(shanghai) # 2022-10-20 08:58:01.954312+08:00
print(Eirunepe) # 2022-10-19 19:58:01.954312-05:00
# 时间的替换(tzinfo:时区),修改时间元祖中的值。
import datetime
t_new = datetime.datetime.now()
t_replace = t_new.replace(year=1997, tzinfo=None)
print(t_replace) # 1997-10-20 10:14:35.412129
random 随机数模块
随机数
import random
# 随机小数,如:发随机红包
ran = random.random() # 大于0且小于1之间的小数
ran2 = random.uniform(1, 3) # 大于1小于3的小数
print(ran, ran2) # 0.9538540358671055 2.290364330364932
# 随机整数
ran3 = random.randint(1, 5) # 大于等于1且小于等于5之间的整数
ran4 = random.randrange(1, 10, 2) # 大于等于1且小于10之间的奇数
print(ran3, ran4) # 4 1
# 随机选择值一个返回
ran5 = random.choice([1, '23', [4, 5]]) # 1 或者 23 或者 [4,5]
# 随机选择多个返回,返回的个数为函数的第二个参数
ran6 = random.sample([1, '23', [4, 5]], 2) # 列表元素任意2个组合
print(ran5) # [4, 5]
print(ran6) # [[4, 5], '23']
打乱列表顺序
import random
item = [1, 3, 5, 7, 9]
random.shuffle(item) # 打乱次序
print(item) # [9, 1, 7, 5, 3]
random.shuffle(item)
print(item) # [5, 7, 1, 3, 9]
课堂练习
设计一个四位数的随机验证码的代码,要求每位都可以是大写字母小写字母、数字
import random
def create_code(num):
code = ''
# letter_upper = random.choice([chr(i) for i in range(65, 90)]) # A - Z
# letter_lower = random.choice([chr(i) for i in range(97, 122)]) # a - z
# number = random.choice([chr(i) for i in range(48, 57)]) # 0 - 9
for i in range(num):
code += random.choice([
random.choice([chr(i) for i in range(65, 90)]),
random.choice([chr(i) for i in range(97, 122)]),
random.choice([chr(i) for i in range(48, 57)])
])
return code
ret = create_code(4)
print(ret) # kE4u

浙公网安备 33010602011771号