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]]