Python Collections之defaultdict

2023-03-06  本文已影响0人  羋学僧

Python内置四种基本container:list, dict, set, tuple,collections模块为其补充。defaultdict为collections中一个容器。一言以蔽之,是为有默认值的dict。

dict在python中是非常常见的一种数据类型。

一个官方例子

s为一个list,其中包含了5个tuple

s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]

我们的目标是生成d这样的dict统计颜色对应值列表。

d = [('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

一般来说,我们会这样的想法:新建一个dict,循环s写入到d的值(list)中

d = dict()
for k,v in s:
    d[k].append(v)
print(d)

然后收到以下错误,原因是d中没有为'yellow'的key,引用失败。

Traceback (most recent call last):
    d[k].append(v)
KeyError: 'yellow'

这时候defaultdict就能派上用场了。

classcollections.defaultdict([default_factory[,...]])

defaultdict 是内置 dict 类的子类。它重载了一个方法并添加了一个可写的实例变量。其余的功能与 dict 类相同。

本对象包含一个名为 default_factory 的属性,构造时,第一个参数用于为该属性提供初始值,默认为 None。所有其他参数(包括关键字参数)都相当于传递给 dict 的构造函数。

根据定义,defaultdic只是比dict多了一个方法,而这个方法就是missing, 这个方法与default_factory有关。

如果 default_factory 属性为 None,则调用本方法会抛出 KeyError 异常,附带参数 key。
如果 default_factory 不为 None,则它会被(不带参数地)调用来为 key 提供一个默认值,这个值和 key 作为一对键值对被插入到字典中,并作为本方法的返回值返回。

default_factory

本属性由__missing__()方法来调用。如果构造对象时提供了第一个参数,则本属性会被初始化成那个参数,如果未提供第一个参数,则本属性为None

default_factory可以为很多类型,list、set、str都可以,如果key不存在,返回为默认值。

dict1 = defaultdict(int)
dict2 = defaultdict(set)
dict3 = defaultdict(str)
dict4 = defaultdict(list)

print(dict1[1])
print(dict2[1])
print(dict3[1])
print(dict4[1])
0      int的默认值
set()  set的默认值
       str的默认值
[]     list的默认值

List

使用 list 作为 default_factory,很轻松地将(键-值对组成的)序列转换为(键-列表组成的)字典:

s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
d = defaultdict(list)
for k, v in s:
    d[k].append(v)
print(d)
output:
defaultdict(<class 'list'>, {'yellow': [1, 3], 'blue': [2, 4], 'red': [1]})

Int

设置 default_factory 为 int,使 defaultdict 用于计数(类似其他语言中的 bag 或 multiset):

str = 'chinese'
d = defaultdict(int)
for k in str:
    d[k] += 1
print(d)
output:
defaultdict(<class 'int'>, {'c': 1, 'h': 1, 'i': 1, 'n': 1, 'e': 2, 's': 1})

当一个字母首次遇到时,它会查询失败,则 default_factory 会调用 int() 来提供一个整数 0 作为默认值。后续的自增操作建立起对每个字母的计数。

Set

设置 default_factory 为 set 使 defaultdict 用于构建 set 集合:

s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]
d = defaultdict(set)
for k, v in s:
    d[k].add(v)
print(d)
output:
defaultdict(<class 'set'>, {'red': {1, 3}, 'blue': {2, 4}})

Lambda

Lambda函数更为灵活的指定默认值,可以为任意值。

strings = 'chinese'
counts = defaultdict(lambda: 0)
for i in strings:
    counts[i] +=1
print(counts)
output:
defaultdict(<function <lambda> at 0x7fe1b1b3d170>, {'c': 1, 'h': 1, 'i': 1, 'n': 1, 'e': 2, 's': 1})

#和int一样的效果
test = defaultdict(lambda : 'hello')
test[1]
test[2] = 'two'
print(test)
output:
defaultdict(<function <lambda> at 0x7fe338b11170>, {1: 'hello', 2: 'two'})

之前的输出都是连带着defaultdict里default_factory都输出了,但是一般没有必要,只需要使用item。

s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]
d = defaultdict(set)
for k, v in s:
    d[k].add(v)
print(d)
print(d.items())
output:
defaultdict(<class 'set'>, {'red': {1, 3}, 'blue': {2, 4}})
dict_items([('red', {1, 3}), ('blue', {2, 4})])
上一篇 下一篇

猜你喜欢

热点阅读