ata[key]()
KeyError: 'primary'
内置列表类型可以满足许多数据结构的需求。然而,有时候需要不同性能权衡的替代实现。
array
模块提供一个array()
对象,就像一个只存储同类型数据,并且存储更加紧凑的列表一样。以下示例展示一个数字数组,它以两个字节无符号二进制数(typecode为"H"
)存储,而不是通常的每个对象16字节的常规Python整数对象列表:
>>> from array import array
>>> a = array('H', [4000, 10, 700, 22222])
>>> sum(a)
26932
>>> a[1:3]
array('H', [10, 700])
collections
模块提供deque()
对象,就像一个拥有速度更快的左端添加和移除操作,更慢的中间查找速度的列表一样。这些对象适用于实现队列以及宽度优先树搜索:
>>> from collections import deque
>>> d = deque(["task1", "task2", "task3"])
>>> d.append("task4")
>>> print("Handling", d.popleft())
Handling task1
unsearched = deque([starting_node])
def breadth_first_search(unsearched):
node = unsearched.popleft()
for m in gen_moves(node):
if is_goal(m):
return m
unsearched.append(m)
除了可选的列表实现外,库也提供了其他工具,比如具有操作有序列表函数的bisect
模块:
>>> import bisect
>>> scores = [(100, 'perl'), (200, 'tcl'), (400, 'lua'), (500, 'python')]
>>> bisect.insort(scores, (300, 'ruby'))
>>> scores
[(100, 'perl'), (200, 'tcl'), (300, 'ruby'), (400, 'lua'), (500, 'python')]
heapq
模块提供了基于常规队列实现堆的函数。最小值的实体总是放在位置0处。这对于需要重复访问最小元素但是不想要对整个列表排序的应用很有用:
>>> from heapq import heapify, heappop, heappush
>>> data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
>>> heapify(data) # rearrange the list into heap order
>>> heappush(data, -5) # add a new entry
>>> [heappop(data) for i in range(3)] # fetch the three smallest entries
[-5, 0, 1]
11.8 Decimal Floating Point Arithmetic
decimal
模块为十进制浮点算法提供Decimal
数据类型。与二进制浮点型的内嵌的float
实现相比,这个类在以下场合及其有用:
- 金融类应用以及其他需要精确十进制表示的应用;
- 控制精度;
- 控制舍入以满足法律上或者管控上的需求;
- 追踪重要的小数位数,或者
- 用户其他输出与手工计算匹配的应用
例如,计算对70分的电话费取5%的税,十进制浮点型盒二进制浮点型结果不同。当结果需要舍入到最近的整分时,它们之间的差异就很重要了:
>>> from decimal import *
>>> round(Decimal('0.70') * Decimal('1.05'), 2)
Decimal('0.74')
>>> round(.70 * 1.05, 2)
0.73
十进制结果保持一个尾随的0,精度自从从两位延伸到了四位。十进制可以重新进行数学运算,就像手工一样,并且避免了二进制浮点数不能精确表示十进制数时会产生的问题。
精确表示使得Decimal
类可以执行求余计算以及不适用于二进制浮点型的比较测试:
>>> Decimal('1.00') % Decimal('.10')
Decimal('0.00')
>>> 1.00 % 0.10
0.09999999999999995
>>> sum([Decimal('0.1')]*10) == Decimal('1.0')
True
>>> sum([0.1]*10) == 1.0
False
decimal
模块提供了必要的高精度算法:
>>> getcontext().prec = 36
>>> Decimal(1) / Decimal(7)
Decimal('0.142857142857142857142857142857142857')