Table of Contents generated with DocToc
Collections
库中的常用方法:
Counter
defaultdict
OrderedDict
deque
namedtuple
计数器
Counter
对象本质上是dict
的子类,其内部结构为:{元素: 元素出现次数}
Counter
: 通常接受一个可迭代对象作为参数,返回每个元素出现的次数elements()
: 方法返回所有元素组成的可迭代对象,包括重复元素most_common(num)
: 以一个数组作为参数,获取重复频率最高的前 num 个元素,返回类型位 Array,Array 中每个元素都是(元素, 重复次数)
的元组形式
from collections import Counter
string = 'this is a counter test to count letter'
counter = Counter(string)
# Counter({'t': 8, ' ': 7, 'e': 4, 's': 3, 'o': 3, 'c': 2, 'n': 2, 'r': 2, 'u': 2, 'i': 2, 'l': 1, 'a': 1, 'h': 1})
counter.most_common(5)
# [('t', 8), (' ', 7), ('e', 4), ('o', 3), ('s', 3)]
Counter
还支持一些类似集合的运算
from collections import Counter
example_list1 = ['a', 'b', 'a', 'c']
example_list2 = ['a', 'a', 'a', 'b']
# + 计数器相加
Counter(example_list1) + Counter(example_list2)
# Counter({'a': 5, 'b': 2, 'c': 1})
# - 第一个计数器有,而第二个没有的元素
Counter(example_list1) - Counter(example_list2)
# Counter({'c': 1})
# & 交集,取两者共有的项的较小计数
Counter(example_list1) & Counter(example_list2)
# Counter({'a': 2, 'b': 1})
# | 并集,相同的元素则取较大的计数
Counter(example_list1) | Counter(example_list2)
# Counter({'a': 3, 'b': 1, 'c': 1})
除此以外,还有一个subtract
方法,用于两个Counter
之差:
c = Counter(a=4, b=2, c=0, d=-2)
d = Counter(a=1, b=2, c=3, d=4)
# 将会直接在 c 上进行操作
c.subtract(d)
print(c)
# Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})
一个传统的字典,如果通过dict[key]
去获取一个不存在的key
的值时,则会报错。而defaultdict
则在构造时传入一个方法,之后如果要获取的key
不存在,则会调用该方法,返回方法调用的结果。
from collections import defaultdict
def default_func():
return None
result = defaultdict(default_func)
for i in range(10):
result[i] = i
print(result) # defaultdict(<function default_func at 0x39577c>, {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9})
print(result[99]) # None
字典是无序的,每次遍历时的顺序都可能会不一样。而通过OrderedDict
,可以创建一个有序字典,它会记忆字典的键添加的顺序,迭代时会按照相同的顺序返回。
from collections import OrderedDict
example_dict = {
'a': 1,
'b': 2,
'c': 3
}
# 确保传入 OrderedDict 的值是排好序的
orderedDict = OrderedDict(sorted(example_dict.items(), key=lambda t: t[0]))
# 或者:
example_dict = (
('a', 1),
('b', 2),
('c', 3)
)
orderedDict = OrderedDict(example_dict)
# 之后遍历会按照初始化 OrderedDict 时的顺序
for key in orderedDict:
print(key)
# a
# b
# c
# OrderedDict 的 Key 会按照插入的顺序排列,不是Key本身排序
od = OrderedDict()
od['z'] = 1
od['y'] = 2
od['x'] = 3
od.keys() # 按照插入的 Key 的顺序返回
# ['z', 'y', 'x']
deque
是双端队列,可从队列头部或尾部快速增加和取出对象。除此以外,可以在实例化deque
的时候限制最大长度,之后如果长度超出了最大长度,则头部的元素会自动出栈。
在初始化时传入一个序列,返回一个双端队列。它的常用 API 有:
pop()
去掉最右边的项并返回该项popleft()
可去掉最左边的项并返回该项append(x)
把元素加在左边appendleft(x)
把元素加在左边extend(iterable)
在右侧合并一个可迭代对象extendleft(iterable)
在左侧合并一个可迭代对象insert(index, x)
在index
位置上添加一个元素remove(value)
删除匹配的第一个元素;如果没有匹配元素则抛出ValueError
reverse()
反转队列rotate(iterable)
队列的旋转操作rotate
参数为正时,由队列尾开始往前,依次把元素移动到队列首部,直到移动参数数目的元素;rotate
参数为负时,由队列首开始往后,依次把元素移动到队列尾部,直到移动参数数目的元素
from collections import deque
# 可以通过很多方式初始化一个双端队列
d = deque() # 空队列
d.append(1)
d.append(2)
d.append(3)
# deque([1, 2, 3])
d = deque(range(7)) # deque([0, 1, 2, 3, 4, 5, 6])
d.pop() # 返回 6
d.popleft() # 返回 0
d.appendleft(11) # 返回 None
d.extend(['a', 'b', 'c'])
print(d) # deque([11, 1, 2, 3, 4, 5, 'a', 'b', 'c'])
# reverse & rotate
from collections import deque
d = deque(range(5))
print(d) # deque([0, 1, 2, 3, 4])
# reverse
d.reverse() # deque([4, 3, 2, 1, 0])
d.reverse() # deque([0, 1, 2, 3, 4])
# rotate
d.rotate(2) # 从队尾开始,把 2 个元素移到队首
print(d) # deque([3, 4, 0, 1, 2])
d.rotate(5)
print(d) # deque([3, 4, 0, 1, 2]) 当参数大于等于列表长度的时候则无效
d2 = deque(range(5))
print(d2) # deque([0, 1, 2, 3, 4])
d2.rotate(-2) # 从队首开始,把 2 个元素移到队尾
print(d2) # deque([2, 3, 4, 0, 1])
d2.rotate(-5)
print(d2) # deque([2, 3, 4, 0, 1]) 当参数的绝对值大于等于列表长度的时候则无效
通过maxlen
来限制队列最大长度:
from collections import deque
d = deque(range(5), maxlen=10)
print(d) # deque([0, 1, 2, 3, 4], maxlen=10)
d.extend([1, 2, 3, 4, 5, 6, 7, 8, 9])
print(d) # deque([4, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)
命名元组。通过命名元组创建的对象具有元组的特性,而且可以通过位置索引 & 键值索引获取到元组内的数据。
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)
print(p) # Point(x=1, y=2)
# 通过属性引用
p.x # 1
p.y # 2
# 通过索引引用
p[0], p[1] # (1, 2)
p[0] + p[1] # 3
x, y = p
x, y # (1, 2)
namedtuple
用来创建一个自定义的tuple
对象,并且规定了tuple
元素的个数,可以用属性或者索引来引用tuple
的某个元素。
命名元组的内置方法:
_asdict()
将命名元组转换为OrderedDict
_replace(kwargs)
替换命名元组内的某些值,不修改旧命名元组,返回一个新命名元组_make(iterable)
实例化命名元组时的方法_fields()
返回命名元组中 key 组成的元组
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)
# 或者使用 _make
# p = Point._make([1, 2])
dict = p._asdict()
print(dict) # OrderedDict([('x', 1), ('y', 2)])
new_p = p._replace(x=3)
print(new_p) # Point(x=3, y=2)
print(p) # Point(x=1, y=2)
keys = p._fields()
print(keys) # ('x', 'y')