一、 collections模块:更多数据结构
import collections
1. 计数器
可以使用 Counter(seq) 对序列中出现的元素个数进行统计。
例如,我们可以统计一段文本中出现的单词及其出现的次数:
>>> import collections
>>> from string import punctuation
>>> sentence = "one, two, three, one, two, three, I come from China."
>>> words_count = collections.Counter(sentence.translate(None, punctuation).lower().split())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: translate() takes exactly one argument (2 given)
>>> words_count = collections.Counter(sentence.translate(punctuation).lower().split())
>>> print(words_count)
Counter({'one,': 2, 'two,': 2, 'three,': 2, 'china.': 1, 'come': 1, 'from': 1, 'i': 1})
2. 双端队列
双端队列支持从队头队尾出入队:
>>> import collections
>>> dq = collections.deque()
>>> for i in range(10):
... dq.append(i)
...
>>> print(dq)
deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> print(dq.pop())
9
>>> print(dq)
deque([0, 1, 2, 3, 4, 5, 6, 7, 8])
>>> for i in range(10):
... print(dq.pop())
...
8
7
6
5
4
3
2
1
0
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
IndexError: pop from an empty deque
>>> print(dq)
deque([])
>>> for i in range(10):
... dq.appendleft(i)
...
>>> print(dq)
deque([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
>>> for i in range(10):
... print(dq.popleft())
...
9
8
7
6
5
4
3
2
1
0
列表 VS 双端队列
双端队列支持线程安全,在双端队列的任何一端执行添加和删除操作,它们的内存效率几乎相同(时间复杂度为O(1))。
虽然list也支持类似的操作,但是它对定长列表的操作表现很不错,而当遇到pop(0)和insert(0, v)这样既改变了列表的长度又改变其元素位置的操作时,其时间复杂度就变为O(n)了。
在双端队列中最好不使用切片和索引,你可以用popleft和appendleft方法,双端队列对这些操作做了优化。在两端的索引访问时间复杂度为O(1),但是访问中间元素的时间复杂度为O(n),速度较慢,对于快速随机的访问,还是用列表代替。
列表用于随机访问和定长数据的操作,包括切片,而双端队列适用于在两端压入或弹出元素,索引(但不包括切片)的效率可能低于列表。
class Deque:
"""模拟双端队列"""
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def addFront(self, item):
self.items.append(item)
def addRear(self, item):
self.items.insert(0,item)
def removeFront(self):
return self.items.pop()
def removeRear(self):
return self.items.pop(0)
def size(self):
return len(self.items)
# 以下是测试代码
d = Deque()
print(d.isEmpty())
d.addRear(4)
d.addRear('dog')
d.addFront('cat')
d.addFront(True)
print(d.size())
print(d.isEmpty())
d.addRear(8.4)
print(d.removeRear())
print(d.removeFront())
#输出
True
4
False
8.4
True
3. 有序字典
字典的key按顺序排列:
import collections
items = (
('A', 1),
('B', 2),
('C', 3)
)
regular_dict = dict(items) # 无序输出
ordered_dict = collections.OrderedDict(items) # 有序输出
print('Regular Dict:')
for k, v in regular_dict.items():
print(k, v)
print('Ordered Dict:')
for k, v in ordered_dict.items():
print(k, v)
# 输出如下:
Regular Dict:
A 1
C 3
B 2
Ordered Dict:
A 1
B 2
C 3
4. 带默认值的字典
对于 Python 自带的词典 d,当 key 不存在的时候,调用 d[key] 会报错,但是 defaultdict 可以为这样的 key 提供一个指定的默认值,我们只需要在定义时提供默认值的类型即可,如果 key 不存在返回指定类型的默认值:
>>> import collections
>>> dd = collections.defaultdict(list)
>>> print(dd["foo"])
[]
>>> dd = collections.defaultdict(int)
>>> print(dd["foo"])
0
>>> dd = collections.defaultdict(float)
>>> print(dd["foo"])
0.0