Python 实用库介绍

Python 实用库介绍

bisect 管理有序列表

bisect 模块包含两个主要的函数,bisect 和 insort,两个函数都利用二分查找算法来在有序序列中查找和插入元素。

# BEGIN BISECT_DEMO
import bisect
import sys

HAYSTACK = [1, 4, 5, 6, 8, 12, 15, 20, 21, 23, 23, 26, 29, 30]
NEEDLES = [0, 1, 2, 5, 8, 10, 22, 23, 29, 30, 31]

ROW_FMT = '{0:2d} @ {1:2d}    {2}{0:<2d}'

def demo(bisect_fn):
    for needle in reversed(NEEDLES):
        position = bisect_fn(HAYSTACK, needle)  # <1>
        offset = position * '  |'  # <2>
        print(ROW_FMT.format(needle, position, offset))  # <3>

if __name__ == '__main__':

    if sys.argv[-1] == 'left':    # <4>
        bisect_fn = bisect.bisect_left
    else:
        bisect_fn = bisect.bisect

    print('DEMO:', bisect_fn.__name__)  # <5>
    print('haystack ->', ' '.join('%2d' % n for n in HAYSTACK))
    demo(bisect_fn)

# END BISECT_DEMO
'''
DEMO: bisect
haystack ->  1  4  5  6  8 12 15 20 21 23 23 26 29 30
31 @ 14      |  |  |  |  |  |  |  |  |  |  |  |  |  |31
30 @ 14      |  |  |  |  |  |  |  |  |  |  |  |  |  |30
29 @ 13      |  |  |  |  |  |  |  |  |  |  |  |  |29
23 @ 11      |  |  |  |  |  |  |  |  |  |  |23
22 @  9      |  |  |  |  |  |  |  |  |22
10 @  5      |  |  |  |  |10
 8 @  5      |  |  |  |  |8
 5 @  3      |  |  |5
 2 @  1      |2
 1 @  1      |1
 0 @  0    0
'''
import bisect
import random

SIZE = 7

random.seed(1729)

my_list = []
for i in range(SIZE):
    new_item = random.randrange(SIZE*2)
    bisect.insort(my_list, new_item)
    print('%2d ->' % new_item, my_list)

'''
10 -> [10]
 0 -> [0, 10]
 6 -> [0, 6, 10]
 8 -> [0, 6, 8, 10]
 7 -> [0, 6, 7, 8, 10]
 2 -> [0, 2, 6, 7, 8, 10]
10 -> [0, 2, 6, 7, 8, 10, 10]
'''

其中 bisect 和 insort 函数(本质就是 bisect_left 和 insort_left)都有一个类似的 bisect_right 和 insort_right,他们的差别就是如果列表中存在计算结果相同的元素,那么新的元素将插入在这些元素的左边还是右边。

array 高效地数值存储结构

虽然列表既灵活又简单,但由于其是容器结构(其中存储的并不是具体数值,而是对应元素的指针,虽然这使得它应用范围更广,但所需要的访问和存储都要更大),因此如果存储的内容只是数值,则可以采用 array,其背后存的并不是 float 对象,而是数字的机器翻译。同时,array 支持几乎所有的 list 操作。

from array import array
from random import random
floats = array('d', (random() for i in range(10**7)))
print(floats[-1])
# 0.7030774022684948
fp = open("floats.bin", 'wb')
floats.tofile(fp)
fp.close()
floats = array('d')
fp = open("floats.bin", 'wb')
floats2.fromfile(fp, 10**7)
fp.close()
print(floats2[-1])
# 0.7030774022684948
print(floats == floats2)
# True

由于 array 只允许其中存储某类数值,因此在创建时需要指定存储的数据类型。具体的类型名称如下表所示。

memoryview 内存视图

memoryview 让用户在不复制内容的情况下操作同一个数组的不同切片。

import array

numbers = array.array('h', [-2, -1, 0, 1, 2])
memv = memoryview(numbers)
print(len(memv)) # 5
print(memv[0]) # -2
memv_oct = memv.cast('B')
print(memv_oct.tolist()) # [254, 255, 255, 255, 0, 0, 1, 0, 2, 0]
memv_oct[5] = 4
print(numbers)
# array('h', [-2, -1, 1024, 1, 2])

其中创建了数据 numbers 的另一个别名 memv,在之后通过 memv.cast 实现了数据类型的转换。同时,如果修改 memv,那么原始数据也将被修改。

deque 双向队列

collections.deque 类是一个线程安全、可以快速从两端添加和删除元素的数据结构。而且如果想要有一种数据类型来存储“最近用到的几个元素”,deque 也是一个很好的选择。这是因为在新建一个双向队列的时候,你可以指定这个队列的大小,如果这个队列满员了,还可以从反向删除过期的元素,然后在尾端添加新的元素。

from collections import deque

dq = deque(range(10), maxlen=10)
print(dq) # deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)
dq.rotate(3)
print(dq) # deque([7, 8, 9, 0, 1, 2, 3, 4, 5, 6], maxlen=10)
dq.rotate(-4)
print(dq) # deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 0], maxlen=10)
dq.appendleft(-1)
print(dq) # deque([-1, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)
dq.extend([11, 22, 33])
print(dq) # deque([3, 4, 5, 6, 7, 8, 9, 11, 22, 33], maxlen=10)
dq.extendleft([10, 20, 30, 40])
print(dq) # deque([40, 30, 20, 10, 3, 4, 5, 6, 7, 8], maxlen=10)

deque 支持几乎所有 list 操作,不过 deque 并不支持 pop(p) 操作。

queue 队列

其提供了同步(线程安全)类 Queue、LifoQueue 和 PriorityQueue,不同的线程可以利用这些数据类交换信息。这三个类的构造方法都有一个可选参数 maxsize,它接受正整数作为输入,用来限定队列的大小。但是在满员的时候,这些类不会扔掉旧的元素来腾出位置。相反,如果队列满了,它就会被锁住,知道另外的线程移除了某个元素而腾出了位置。这一特性让这些类很适合用来控制活跃线程的数量。

multiprocessing 这个包实现了自己的 Queue,它跟 queue.Queue 类似,是设计给进程间通信用的。同时还有一个专门的 multiprocessing.JoinableQueue 类型,可以让任务管理变得更方便。

asyncio 包有 Queue、LifoQueue、PriorityQueue 和 JoinableQueue,这些类专门为异步编程里的任务管理提供了专门的便利。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值