Item 46: Use Built-in Algorithms and Data Structures

 使用内置数据结构和算法        python

        当你实现很是小的的Python程序时,你可能会看到由你的代码的算法复杂性而形成的减速。 这个一般不是Python语言自己速度的形成,这更有多是由于没有为您的问题使用最好的算法和数据结构。幸运的是Python标准库有许多内置的算法和数据结构能够使用。除了速度,使用这些经常使用的算法和数据结构可让你的生活更轻松。 你可能想使用的一些更有力的工具,这是一个棘手的问题。 避免从新实现经常使用功能将会节省您的时间。算法

        Double-ended Queue(双端队列)
        deque类是在collections模块中,它是一个double-ended队列。从deque队列开始或者结尾,插入或者删除会花费相同的时间。这个使其成为先进先出(FIFO)队列的理想选择。数据结构

fifo = deque()
fifo.append(1) # Producer
x = fifo.popleft() # Consumer

内置List也能够实现有序队列,如fifo。但内置List从列表头部的插入或删除项,花费时间是线性的,这比常数慢得多。app

        Ordered Dictionary(有序字典)
        标准字典是无序的。 这意味着具备相同的键和值的dict能够有不一样的迭代次序。 这种行为有一个使人惊讶的副产品就是实现字典的快速哈希表。dom

a = {}
a['foo'] = 1
a['bar'] = 2
# Randomly populate ‘b’ to cause hash conflicts
while True:
z = randint(99, 1013)
b = {}
for i in range(z):
b[i] = i
b['foo'] = 1
b['bar'] = 2
for i in range(z):
del b[i]
if str(b) != str(a):
break
print(a)
print(b)
print('Equal?', a == b)
>>>
{'foo': 1, 'bar': 2}
{'bar': 2, 'foo': 1}
Equal? True

        collections模块中的OrderedDict类是一种特殊类型的字典,它跟踪其键的插入顺序。 迭代键OrderedDict具备可预测的行为。 这能够大大简化测试和调试经过使全部代码肯定性。数据结构和算法

a = OrderedDict()
a['foo'] = 1
a['bar'] = 2
b = OrderedDict()
b['foo'] = 'red'
b['bar'] = 'blue'
for value1, value2 in zip(a.values(), b.values()):
print(value1, value2)
>>>
1 red
2 blue

        Default Dictionary
        字典对记帐和跟踪统计很是有用。内建的字典类型是不能假设任何键已经存在。 这使得它作一些简单的事情时显得笨拙,如增长一个存储在字典中的计数器。函数

stats = {}
key = 'my_counter'
if key not in stats:
    stats[key] = 0
stats[key] += 1

collections模块中的defaultdict类简化了当key不存在时自动存储默认值。 全部你须要作的是提供每次键丢失时将返回默认值的函数。 在这里例如,int内置函数返回0如今,递增计数器是
简单。int()->0工具

stats = defaultdict(int)
stats['my_counter'] += 1

        Heap Queue
   关于这里,heap这种数据结构的介绍有一个简单的blog能够去看一下http://blog.csdn.net/minxihou/article/details/51857518
堆是用于维护优先级队列的有用数据结构。 heapq模块提供了在标准list类型中建立堆的功能使用函数heappush,heappop和nsmallest等函数。任何优先级的项能够按任何顺序插入堆中。测试

a = []
heappush(a, 5)
heappush(a, 3)
heappush(a, 7)
heappush(a, 4)

老是先移除最高优先级(lowest number)的项..net

print(heappop(a), heappop(a), heappop(a), heappop(a))
>>>
3 4 5 7

生成的list在heapq以外很容易使用。 访问堆的0索引将老是返回最小的项。

a = []
heappush(a, 5)
heappush(a, 3)
heappush(a, 7)
heappush(a, 4)
assert a[0] == nsmallest(1, a)[0] == 3

list的sort方法保持不变。

print('Before:', a)
a.sort()
print('After:' , a)
>>>
Before: [3, 4, 7, 5]
After: [3, 4, 5, 7]

        Bisection

        调用index方法查找列表中的项须要花费与list长度成线性比例的时间。

x = list(range(10**6))
i = x.index(991234)

使用bisect模块的方法,如:bisect_left,是使用二分查找的方法。它返回的索引是插入点值插入序列。

i = bisect_left(x, 991234)

二分搜索的复杂度是对数的。 这意味着使用bisect搜索100万个项的list的速度是使用线性索引方式搜索的14倍。It’s way faster!

        Iterator Tools
        tertools内置模块包含大量有用与迭代器相关的函数。不是全部这些都在Python 2中可用,但它们能够轻松地使用经过查看模块中记录的simple recipes。 请参阅help(itertools)得到更多详细信息。
itertools中的函数主要分为三类:
    Linking iterators together
        •chain:将多个迭代器组合成一个顺序迭代器。
        •cycle:一直重复迭代器的项。
        •tee:将单个迭代器拆分为多个并行迭代器。
        •zip_longest:内置zip函数的变体,当迭代的几个对象长度不一样的时候有更好的表现。
    Filtering items from an iterator
        •islice:经过数字索引切片迭代器,而不进行复制。
        •takewhile:当断言函数返回Ture时返回迭代器中的项。
        •dropwhile:当断言函数第一次为False时,返回迭代器中的项。
        •filterfalse:当断言函数第一次为False时,返回迭代器中全部的项。 与内置函数filter做用相反。
    Combinations of items from iterators(组合迭代器中的项)
        •product:返回迭代器中项的笛卡尔乘积,是一种很好的替代深层嵌套列表推导的方法。
        •permutations:返回长度为N的有序排列迭代器。
        •combination:返回长度为N的,用迭代器中未重复项所组成的无序组合。
在itertools模块中有更多的功能和recipes可用不能在这里一一说起。 每当你发现本身处理一些棘手的迭代代码,itertools文档是值得再次查看,看看是否有你想要的东西。

        Things to Remember
        一、使用Python的内置模块用于算法和数据结构。   

        二、不要本身从新实现此功能。

相关文章
相关标签/搜索