python的强大众所周知
我们使用 python 的开发者,除了因为它在世界上非常火爆,训练 ai 还得学它,更重要的一点其实应该是它庞大的社区,丰富的第三方库资源。
现在几乎任何领域,都能在 python 的 pypi 上找到相应的第三方库,如果你是办公室白领,openxyl 可以为你带来强大的 excel 自动化处理能力;如果你是力学结构,那么 scipy 可以提供丰富的算法;如果你是机器视觉方面工作者,opencv-python 可以为你完成绝大部分工作……
本篇文章不讨论需要安装的 第三方库,而是来宣传宣传那些比较冷门的、不常见的,但十分强大的 python 内置标准库。
1. contextlib
contextlib 为涉及 with 相关的语法提供了更加实用的一些工具。
1.1 suppress
我们先来看一个场景,当需要读取一个 可能不存在 的文件时,我们会这么操作:
普通代码
try:
with open('test.txt', 'r') as f:
f.read()
except FileNotFoundError:
pass
接下来看 suppress() 来如何高效操作:
suppress 代码
from contextlib import suppress
with suppress(FileNotFoundError):
with open('test.txt', 'r') as f:
f.read()
suppress() 将捕获异常,不需要写长串的 try 块代码。
1.2 contextmanager
如果我们需要实现自己的 with 上下文管理,普通情况是这么写:
普通代码
class MyOpen:
def __init__(self, path='', mode='w'):
self.file = open(path, mode)
def __enter__(self):
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
self.file.close()
with MyOpen('test.txt', 'r') as f:
f.read()
这个方式需要创建一个 类 来实现,现在换成 contextmanager 来实现一个 with :
contextmanager 代码
from contextlib import contextmanager
@contextmanager
def my_open(path='', mode='w'):
file = open(path, mode)
try:
yield file
finally:
file.close()
with my_open('test.txt', 'r') as f:
f.read()
2. itertools
itertools 是为了高效循环而创建迭代器的模块。
2.1 permutations
permutations() 可以获取全部排列,我们先来看一个普通代码示例。
我希望获得 1、2、3 三个数字的全部组合,我们会这么写:
普通代码
def get_permutations(nums):
# 如果列表为空,返回空列表
if not nums:
return []
# 如果列表只有一个元素,返回该元素本身
if len(nums) == 1:
return [nums]
# 用于存储所有排列的结果
result = []
# 遍历列表中的每个元素
for i in range(len(nums)):
# 当前元素
current_num = nums[i]
# 剩余元素
remaining_nums = nums[:i] + nums[i + 1:]
# 递归获取剩余元素的排列
for perm in get_permutations(remaining_nums):
# 将当前元素与剩余元素的排列组合
result.append([current_num] + perm)
return result
num_list = [1, 2, 3]
results = get_permutations(num_list)
for res in results:
print(res)
可以看到简单的需求实现起来却非常复杂,现在换成 permutations() 来实现:
permutations 代码
from itertools import permutations
num_list = [1, 2, 3]
results = permutations(num_list)
for res in results:
print(res)
注意:itertools 的返回是迭代器,需要用迭代器的方法获取内容。
2.2 cycle
或许在日常工作中,你经常需要无限循环一个数列,例如 A、B、C、A、B、C、A、B、C…… ,这个在正常开发中会这么写:
普通代码
import time
words = ['A', 'B', 'C']
current_index = 0
while True:
word = words[current_index]
print(word)
current_index += 1
if current_index >= len(words):
current_index = 0
time.sleep(1)
现在我们有了更方便的选择:cycle。它的代码如下:
cycle 代码
from itertools import cycle
import time
words = ['A', 'B', 'C']
cycle_seq = cycle(words)
while True:
word = next(cycle_seq)
print(word)
time.sleep(1)
3. argparse
在很多时候,我们开发的 python 工具都不是 可视化产品,更多的是 命令行工具,这样可以省去很多工作。
如果我们有个脚本工具可以使用命令行执行,它可以展示版本号功能和填一个数字 计算加上5之后的和,我们可以这样写:
普通代码
import sys
if __name__ == '__main__':
if '-v' in sys.argv or '--version' in sys.argv:
print('v3.1')
elif '-add' in sys.argv:
index = sys.argv.index('-add') + 1
try:
num = int(sys.argv[index])
print(5 + num)
except Exception as e:
print('没有数字')
调用脚本
# 查看版本
python tool.py -v
# 计算 10 + 5 的和
python tool.py -add 10
这里需要我们去处理很多东西,非常复杂,现在换为 argparse 来试一下:
argparse 代码
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser(
prog='项目',
description='这个项目用来测试',
epilog='这里是帮助语句底部内容'
)
parser.add_argument('-v', '--version', action='store_true', help='查看版本')
parser.add_argument('-add', '--add', type=int, help='计算加5的和')
args = parser.parse_args()
if args.version:
print('v3.1')
if args.add:
print(5 + args.add)
调用方法与上面一致,写法却更加优雅,甚至还额外默认提供了 -h 帮助信息查看,让我们可以调用:
python tool.py -h
返回内容如下:
usage: 项目 [-h] [-v] [-add ADD]
这个项目用来测试
options:
-h, --help show this help message and exit
-v, --version 查看版本
-add ADD, --add ADD 计算加5的和
这里是帮助语句
4. bisect
二分查找法 是非常实用的方法,可以快速定位,如果我们需要自己去实现。
现在有个需求是有个列表 [{'id': 1}, {'id': 2}, {'id': 6}, {'id': 8}] ,它是有序的,现在要插入一个 {'id': 3} 到列表中:
普通代码
def binary_search_right(arr, target):
left, right = 0, len(arr)
while left < right:
mid = (left + right) // 2
if arr[mid]['id'] <= target:
left = mid + 1
else:
right = mid
return left
dicts = [{'id': 1}, {'id': 2}, {'id': 6}, {'id': 8}]
data = {'id': 3}
# 获取插入的位置
index = binary_search_right(dicts, data['id'])
print(index)
实现的代码还是比较复杂的,现在来看 bisect 的功力:
bisect 代码
from bisect import bisect_right
dicts = [{'id': 1}, {'id': 2}, {'id': 6}, {'id': 8}]
data = {'id': 3}
ids = [item['id'] for item in dicts]
index = bisect_right(ids, data['id'])
print(index)
结尾
今天我们介绍了四款不常用但非常强大的内置标准库,它们不需要额外进行 pip 安装就可 开袋即食。
当然还有许多强大的 内置标准库,你还知道哪些,快来留言告诉我吧!