defaultdict引入
现在假设这样一种情况,有一组列表字符串。我们需要统计每个字符串出现的次数,并以键值对的形式保存起来。下面先来演示一个错误的写法。
a = ['a','b','r','a','d','r']
b = {}
for i in a: b[i] += 1
print(b)
Traceback (most recent call last): File "D:/Spider_base/test.py", line 5, in <module> b[i] += 1KeyError: 'a'
报错的原因是,字典对于不存在key直接取值的话,会显示KeyError。如果不想报错,我们就需要加上一个判断,对于不存在的key,我们就加上,并赋予初值为1。如下:
a = ['a','b','r','a','d','r']
b = {}
for i in a: if i in b.keys(): b[i] += 1 else: b[i] = 1
print(b)
{'a': 2, 'b': 1, 'r': 2, 'd': 1}
对于上述代码,我们还可以进行优化,即使用字典的setdefault来代替if语句。对于不存在的key赋予默认值0,存在的key就不做任何操作。
a = ['a','b','r','a','d','r']
b = {}
for i in a: b.setdefault(i,0) b[i] += 1
print(b)
{'a': 2, 'b': 1, 'r': 2, 'd': 1}
问题来了,我们还可以再优化吗?上一次优化虽然去除了if语句,但对于每一个key,我们都需要进行判断是否需要给一个默认值。
defaultdict
答案是可以再次优化,python提供了一种默认值字典的数据结构。它允许我们在定义字典时给所有不存在的key设置默认值,这样当取不存在的key时,就不会报错。
from collections import defaultdict
a = ['a','b','r','a','d','r']
b = defaultdict(int)
for i in a: b[i] += 1
print(b)
defaultdict(<class 'int'>, {'a': 2, 'b': 1, 'r': 2, 'd': 1})
defaultdict字典相当于是普通字段的强化版,继承原始dict的功能,并赋予了它新的特性。
初始化defaultdict的参数是一个可调用对象,即函数名。int函数就相当于函数如下:
def fun(): return 0
也可以使用匿名函数如下:
b = defaultdict(lambda :0)
也可以使用:list对应[ ],str对应的是空字符串,set对应set( ),int对应0
OrderedDict
使用dict
时,Key是无序的。在对dict
做迭代时,我们无法确定Key的顺序。如果要保持Key的顺序,可以用OrderedDict。
from collections import OrderedDict
a = OrderedDict()
print(a.fromkeys(['a','b','d','c'],'qq'))
OrderedDict([('a', 'qq'), ('b', 'qq'), ('d', 'qq'), ('c', 'qq')])
OrderedDict
的Key会按照插入的顺序排列,不是Key本身排序。
Counter
Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的Interger(包括0和负数)。
- 创建
from collections import Counter
a = Counter()
b = Counter('afdasfdasd')
c = Counter({'a':4,'b':7})
d = Counter(a=4,b=7)
print(a,b,c,d)
Counter() Counter({'a': 3, 'd': 3, 'f': 2, 's': 2}) Counter({'b': 7, 'a': 4}) Counter({'b': 7, 'a': 4})
创建的方式有三种,第一种是空的Counter类,第二种传入一个可迭代对象,可以是str、list、tuple、dict,最后一种是以键值对的形式。
- 访问
因为最后的计数结果是一个字典的样式,故访问通过访问字典的方式,但若查找的key不存在将会报错。
-
most_common([n])
该函数是将计数结果以列表嵌套二元元组的形式返回。参数n表示给最多n个元素计数,且计数量大的优先,默认返回所有计数。
from collections import Counter
b = Counter('afdasfdasd')
print(b)
print(b.most_common())
print(b.most_common(2))
Counter({'a': 3, 'd': 3, 'f': 2, 's': 2})[('a', 3), ('d', 3), ('f', 2), ('s', 2)][('a', 3), ('d', 3)]