Python 标准库详解
引言
本篇文章将详细介绍Python中几个重要的标准库,这些库可以帮助开发者更加高效地编写代码。我们将逐一探讨time
库、random
库、collections
库以及itertools
库,通过具体示例加深理解。
第一部分:时间处理——time库
获取当前时间
Python的time
库提供了多种方法来获取当前时间。例如,localtime()
函数可以获取本地时间,而gmtime()
则返回UTC时间。此外,ctime()
函数可以直接返回格式化的本地时间字符串。
使用time
库获取时间非常简单:
首先导入time
库,然后调用相关函数即可。例如:
time库可以获取当前时间点,通过localtime()
可以获得本地时间,gmtime()
是UTC时间。我们知道全球有时区划分,北京时间比UTC时间早八个小时。要获得这些时间,我们先导入time库,然后直接调用localtime
或gmtime
并打印输出。
时间戳与计时
time
库还提供了获取时间戳的方法,如time()
、perf_counter()
和process_time()
。其中time()
返回自纪元以来的秒数,perf_counter()
和process_time()
则返回相对时间戳。perf_counter()
会记录sleep时间,而process_time()
不会。
通过记录两个时间戳之间的差值,可以实现简单的计时功能。例如:
我们使用上述三个方法分别获得时间戳,打印它们。然后执行一段代码,并让程序暂停五秒钟,再次获得时间戳,查看两个时间戳之间的差异。可以看到t1
非常大,因为其计时起点非常遥远;t2
和t3
是随机取点的间隔,所以绝对值无实际意义。time
和perf_counter
方法计时相同,而process_time
少了五秒,即sleep
的时间。
格式化输出
time
库支持格式化输出时间,可以通过strftime()
函数自定义格式。例如:
设定格式后输出,如“2018年8月29日”。
此外,time.sleep()
可以让程序暂停指定秒数,常用于控制程序执行节奏。
第二部分:随机数生成——random库
随机种子
random
库生成的是伪随机数,这意味着如果使用相同的种子,将会得到相同的结果。如果不设置种子,默认以当前时间为种子。
例如:
将random
库所有方法导入,设置种子为10,生成随机浮点数,再设置种子为10,生成相同的随机浮点数。若不设定种子,则每次生成不同随机数,因为时间不同。
随机整数与浮点数
random
库提供了多种生成随机整数和浮点数的方法:
randint(a, b)
:生成[a, b]之间的随机整数。randrange(stop)
或randrange(start, stop[, step])
:生成[0, stop)或[start, stop)之间的随机整数,后者可以指定步长。random()
:生成[0.0, 1.0)之间的随机浮点数。uniform(a, b)
:生成[a, b]之间的随机浮点数。
例如:
生成一到十之间的整数,生成零到十之间的整数(不含十),生成零到十之间步长为二的随机整数,生成零到一之间的浮点数,生成二点一到三点五之间的浮点数。
操作序列
random
库还提供了对序列操作的方法:
choice(seq)
:从序列中随机选择一个元素。choices(population, weights=None, *, cum_weights=None, k=1)
:从序列中随机选择k个元素,可以选择权重。shuffle(x)
:随机打乱序列。sample(population, k)
:从序列中随机选择k个不重复的元素。
例如:
从列表中随机选择一个元素,从字符串中随机选择一个字符,从列表中重复采样五次,对列表进行随机排列,随机选择三个元素。
概率分布
random
库还支持生成符合特定概率分布的随机数,如正态分布、指数分布等。以正态分布为例,可以使用normalvariate(mu, sigma)
函数。
例如:
生成符合零均值一标准差的正态分布随机数,生成一万个正态分布随机数并绘制直方图。
实际应用示例
微信红包分配
使用random
库可以实现公平的微信红包分配。通过均匀分布确保每个人的期望金额相等。
定义一个函数接收红包金额和人数,前n-1人随机分配金额,最后一人获得剩余金额。确保每人期望金额相等。
验证码生成
生成四位由数字和大小写字母组成的验证码:
使用string.digits
和string.ascii_letters
组合成字符集,从中随机选择四个字符。
第三部分:容器数据类型——collections库
具名元组
collections.namedtuple
允许创建带字段名的元组。例如:
定义一个具名元组Point
,包含x
和y
字段,初始化后可以像普通元组一样使用,同时可以通过字段名访问元素。
计数器
Counter
用于统计元素出现频率,类似于字典,但提供更多便捷功能。例如:
统计字符串和列表中各元素出现次数,提取最常见的两个元素,对计数器执行加减运算。
双向队列
deque
支持高效的两端插入和删除操作。例如:
创建一个双向队列,从两端添加和删除元素。
第四部分:迭代器工具——itertools库
排列组合
itertools
库提供了多种生成排列组合的方法,如product()
、permutations()
、combinations()
和combinations_with_replacement()
。例如:
生成笛卡尔积、排列和组合。
拉链模式
zip()
函数将多个序列按位置组合,形成元组。例如:
将三个序列组合成元组列表。
无穷迭代
itertools
库还提供了几种无穷迭代的方法,如count()
、cycle()
和repeat()
。例如:
生成从十开始的无穷计数器,循环输出字符,重复输出值。
其他迭代器
chain()
将多个可迭代对象连接成一个大的迭代器,enumerate()
为可迭代对象添加索引,groupby()
按规则对可迭代对象分组。例如:
将两个列表连接成一个大的迭代器,为字符串添加索引,按长度对列表分组。
总结
本文详细介绍了Python中几个重要的标准库,包括time
库、random
库、collections
库和itertools
库。这些库不仅功能强大,而且使用简便,能够显著提高开发效率。通过具体示例,我们更好地理解了这些库的使用方法和应用场景。
习题
1. time
库可以用来做什么?
- A. 获取当前时间
- B. 格式化输出时间
- C. 实现计时器功能
- D. 以上全部
答案: D. 以上全部
2. time
库中获取当前时间戳的方法有哪些?
- A.
time()
- B.
perf_counter()
- C.
process_time()
- D. 以上全部
答案: D. 以上全部
3. 关于时间戳的说法正确的是?
- A.
time()
返回自纪元以来的秒数 - B.
perf_counter()
随意取一个时间点到现在的间隔秒数 - C.
process_time()
不会记录sleep
时间 - D. 以上全部
答案: D. 以上全部
4. random
库提供的随机数是?
- A. 真随机数
- B. 伪随机数
- C. 加密随机数
- D. 不确定
答案: B. 伪随机数
5. random
库中生成随机整数的方法有哪些?
- A.
randint(a, b)
- B.
randrange(stop)
- C.
randrange(start, stop, step)
- D. 以上全部
答案: D. 以上全部
6. random
库中生成随机浮点数的方法有哪些?
- A.
random()
- B.
uniform(a, b)
- C. 以上全部
- D. 以上都不是
答案: C. 以上全部
7. random
库中用于序列数据类型的随机函数有哪些?
- A.
choice(seq)
- B.
choices(seq, k)
- C.
shuffle(seq)
- D.
sample(seq, k)
- E. 以上全部
答案: E. 以上全部
8. collections
库中提供的容器数据类型有哪些?
- A.
namedtuple
- B.
Counter
- C.
deque
- D. 以上全部
答案: D. 以上全部
9. itertools
库中常用的迭代器函数有哪些?
- A.
product
- B.
permutations
- C.
combinations
- D.
zip
- E. 以上全部
答案: E. 以上全部
10. itertools
库中用于无穷迭代的函数有哪些?
- A.
count
- B.
cycle
- C.
repeat
- D. 以上全部
答案: D. 以上全部
习题1:模拟三门问题
题目:
模拟经典的三门问题,使用Python中的random
库进行随机选择,并使用numpy
库计算均值。设定不打开门和打开门的概率分别为两个列表,进行10,000次测试,计算并输出两种情况下的均值。
答案:
如果不打开门的概率均值为0.500587,如果改变选择的概率均值为0.5014。
代码:
导入所需的库
import random
import numpy as np
设定不打开门和打开门的概率列表
prob_not_switch = [0, 1]
prob_switch = [1, 0]
进行10000次测试
results_not_switch = [random.choice(prob_not_switch) for _ in range(10000)]
results_switch = [random.choice(prob_switch) for _ in range(10000)]
计算均值
mean_not_switch = np.mean(results_not_switch)
mean_switch = np.mean(results_switch)
输出结果
print(“如果不打开门的概率均值为:”, mean_not_switch)
print(“如果改变选择的概率均值为:”, mean_switch)
习题2:求解24点问题
题目:
求解经典的24点问题,使用Python中的itertools
库中的product
和permutations
函数进行组合排列计算。定义一个除法函数my_divide
,并从加减乘除运算符中选择操作符进行计算。如果结果等于24,则返回操作步骤;否则返回无解。
答案:
使用排列组合方法得到的结果是近似解,例如:8 / (3 - 8 / 3) = 24.9599,使用暴力计算方法可能会得到“impossible”的结果,表示无法精确等于24。
代码:
导入所需库
import itertools
import time
from collections import OrderedDict
定义除法函数
def my_divide(x, y):
return x / y if y != 0 else ‘inf’
定义运算符列表
operators = [‘+’, ‘-’, ‘*’, ‘/’]
第一层循环进行三次操作
for ops in itertools.product(operators, repeat=3):
for nums in itertools.permutations([3, 3, 8, 8]):
expr = f’{nums[0]} {ops[0]} {nums[1]} {ops[1]} {nums[2]} {ops[2]} {nums[3]}’
try:
result = eval(expr)
if abs(result - 24) < 1e-6:
print(f"解为: {expr} = {result}")
break
except ZeroDivisionError:
continue
else:
continue
break
else:
print(“无解”)
暴力计算方法
def brute_force():
results = []
for ops in itertools.product(operators, repeat=3):
for nums in itertools.permutations([3, 3, 8, 8]):
for perm in itertools.permutations(nums):
expr = f’{perm[0]} {ops[0]} {perm[1]} {ops[1]} {perm[2]} {ops[2]} {perm[3]}’
try:
result = eval(expr)
if abs(result - 24) < 1e-6:
results.append((expr, result))
elif abs(result - 24) < 1e-2:
results.append((expr, result, “近似解”))
except ZeroDivisionError:
continue
return results
start_time = time.time()
brute_force_results = brute_force()
end_time = time.time()
for res in brute_force_results:
print(res)
print(f"暴力计算耗时: {end_time - start_time:.2f}秒")