1.array
array模块定义了一个很像list的新对象类型,不同之处在于它限定了这个类型只能装一种类型的元素。array元素的类型是在创建并使用的时候确定的。
如果程序需要优化内存的使用,并且在list中存储的数据都是同样类型的,那么使用array模块很合适。举个例子,如果需要存储一千万个整数,如果用list,那么至少需要160MB的存储空间,然而如果使用array,只需要40MB。但虽然说能够节省空间,array上几乎没有什么基本操作能够比在list上更快。
在使用array进行计算的时候,需要特别注意那些创建list的操作。例如,使用列表推导式(list comprehension)的时候,会将array整个转换为list,使得存储空间膨胀。一个可行的替代方案是使用生成器表达式创建新的array。
import array a = array.array("i", [1, 2, 3, 4, 5]) print(a) b = array.array(a.typecode, (2 * x for x in a)) print(b) import array a = array.array("i", [1, 2, 3, 4, 5]) #'i'代表int类型 for i, x in enumerate(a): a[i] = 2 * x print(a)
结果为
array('i', [1, 2, 3, 4, 5]) array('i', [2, 4, 6, 8, 10]) array('i', [2, 4, 6, 8, 10])
import array from timeit import Timer def arraytest(): a = array.array("i", [1, 2, 3, 4, 5]) b = array.array(a.typecode, (2 * x for x in a)) def enumeratetest(): a = array.array("i", [1, 2, 3, 4, 5]) for i, x in enumerate(a): a[i] = 2 * x if __name__ == '__main__': m = Timer("arraytest()", "from __main__ import arraytest") n = Timer("enumeratetest()", "from __main__ import enumeratetest") print(m.timeit()) # 1.9450468337403641 print(n.timeit()) # 1.3908460522181805
内部修改速度快于重新构建。
2. Heapq
heapq模块使用一个用堆实现的优先级队列。堆是一种简单的有序列表,并且置入了堆的相关规则。
堆是一种树形的数据结构,树上的子节点与父节点之间存在顺序关系。二叉堆(binary heap)能够用一个经过组织的列表或数组结构来标识,在这种结构中,元素N的子节点的序号为2*N+1和2*N+2(下标始于0)。简单来说,这个模块中的所有函数都假设序列是有序的,所以序列中的第一个元素(seq[0])是最小的,序列的其他部分构成一个二叉树,并且seq[i]节点的子节点分别为seq[2*i+1]以及seq[2*i+2]。当对序列进行修改时,相关函数总是确保子节点大于等于父节点。
import heapq class Item: def __init__(self, name): self.name = name def __repr__(self): return 'Item({!r})'.format(self.name) class PriorityQueue: def __init__(self): self._queue = [] self._index = 0 def push(self, item, priority): heapq.heappush(self._queue, (-priority, self._index, item)) self._index += 1 def pop(self): return heapq.heappop(self._queue)[-1] q = PriorityQueue() q.push(Item('foo'), 1) q.push(Item('bar'), 5) q.push(Item('spam'), 4) q.push(Item('grok'), 1) print(q.pop()) # Item('bar') print(q.pop()) # Item('spam') print(q.pop()) # Item('foo') print(q.pop()) # Item('grok')
3. bisect
bisect模块能够提供保持list元素序列的支持。它使用了二分法完成大部分的工作。它在向一个list插入元素的同时维持list是有序的。在某些情况下,这比重复的对一个list进行排序更为高效,并且对于一个较大的list来说,对每步操作维持其有序也比对其排序要高效。
import bisect a = [(0, 100), (150, 220), (500, 1000)] bisect.insort_right(a, (250, 400)) bisect.insort_right(a, (399, 450)) print(a) # [(0, 100), (150, 220), (250, 400), (399, 450), (500, 1000)] print(bisect.bisect(a, (550, 1200))) # 5 bisect.insort_right(a, (550, 1200)) print(a) # [(0, 100), (150, 220), (250, 400), (399
4. weakref
weakref模块能够帮助我们创建Python引用,却不会阻止对象的销毁操作。这一节包含了weak reference的基本用法,并且引入一个代理类。
在开始之前,我们需要明白什么是strong reference。strong reference是一个对对象的引用次数、生命周期以及销毁时机产生影响的指针。
import weakref import gc class MyObject(object): def my_method(self): print('my_method was called!') gc.enable() gc.set_debug(gc.DEBUG_LEAK) obj = MyObject() r = obj gc.collect() assert r is obj # r allows you to access the object referenced: it's there. obj = 1 # Let's change what obj references to gc.collect() assert r is None # There is no object left: it was gc'ed.
5. Pprint
Pprint模块能够提供比较优雅的数据结构打印方式,如果你需要打印一个结构较为复杂,层次较深的字典或是JSON对象时,使用Pprint能够提供较好的打印结果。
假定你需要打印一个矩阵,当使用普通的print时,你只能打印出普通的列表,不过如果使用pprint,你就能打出漂亮的矩阵结构
import pprint matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] a = pprint.PrettyPrinter(width=20) a.pprint(matrix) print(matrix)
>>
[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]