defaultdict 和 default_factory

https://zhuanlan.zhihu.com/p/187917186
容器(collections)是Python附带一个模块,它包含许多容器数据类型,今天先拿出defaultdict来说。

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

colours = (
(‘Yasoob’, ‘Yellow’),
(‘Ali’, ‘Blue’),
(‘Arham’, ‘Green’),
)
dict = {}
for name, colour in colours:
dict[name] = colour
print(dict)
#output: {‘Yasoob’: ‘Yellow’, ‘Ali’: ‘Blue’, ‘Arham’: ‘Green’}
以上是dict的最常见用法,构造 键-值,但是它的缺陷是碰到没有遇到的键,就会报错

print(dict[‘bob’])
#output:KeyError: ‘bob’
这时候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])

output:
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 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 at 0x7fe338b11170>, {1: ‘hello’, 2: ‘two’})

Tips:

之前的输出都是连带着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})])

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值