第十四章:内置模块(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
posted @ 2022-10-20 13:43  亦双弓  阅读(103)  评论(0)    收藏  举报