Python Cookbook-4.10 给字典增加一个条目

任务

给定一个字典d,当k是字典的键时,你想直接使用d[k],若k不是d的键,则这个操作会给字典增加一个新条目 d[k]。

解决方案

字典的 setdefault 方法正是为此而设计的。假设我们正在创建一个由单词到页数的映射,字典将把每个单词映射到这个词出现过的页的页码构成的列表。这个应用中关键的代码段可能是这样的:

def addword(theIndex, word, pagenumber):
	theIndex.setdefault(word,[]).append(pagenumber)

这段代码等价于下面的更加详尽的版本:

def addword(theIndex, word, pagenumber):
	if word in theIndex:
		theIndex[word].append(pagenumber)
	else:
		theIndex[word] = [pagenumber]

以及:

def addword(theIndex, word, pagenumber):
	try:
		theIndex[word].append(pagenumber)
	except KeyError:
		theIndex[word] = [pagenumber]

使用 setdefault 方法能在相当大的程度上简化实现。

讨论

对于一个字典 d,d.setdefault(k,v)非常接近于 d.get(k,v),后者在前面的 4.9 节曾介绍过。最本质的区别是,如果k不是字典的键,setdefault 方法会将 d[k]赋值为 v,即 d[k]=v(get 则仅仅返回 v,对d不会有任何影响)。因此,当需要类似于 get 的功能,但又需要同时提供这种特殊的效果时,请考虑setdefault 方法。

如果字典中的值是列表,setdefault 方法尤其有用,4.15节会提供更多的细节。最经典的 setdefault 应用大概会是这样:

somedict.setdefault(somekey,[ ]).append(somevalue)

对于不可改变的值,setdefaut 方法就没那么有用了。如果想对单词计数,最好的方法是使用 get,而不是 setdefault:

theIndex[word] = theIndex.get(word, 0) + 1

这是因为反正你也必须要将字典的theIndex[word]的条目重新绑定(因为数字是不可改变的)。不过,针对我们这个单词到页码的例子,你一定不想由于下面这样的写法而造成性能上的损失:

def addword(theIndex,word,pagenumber):
	theIndex[word] = theIndex.get(word,[])+[pagenumber]

让我们看看最后这个版本的 addword,每次调用它的时候都将创建3个新的列表:一个被作为第二个参数传递给 theIndex.get 的空列表,一个只含有一个元素 pagenumber 的列表,以及将前面两者拼接而得到的有 N+1个元素的列表(N是 word 之前出现的次数)。创建这么多列表很显然会降低整体性能。举个例子,在我的计算机上,我对出现在1000页中的4个单词所进行的索引操作计时。用 addword 的第一个版本来作为参考,第二个版本(使用 try/except)快了约10%,第三个版本(使用 setdefault)则慢了约 20%——这种性能差异基本上无关紧要。但第四个版本(使用get)慢了4倍,这样的性能损失恐怕就不能视若无睹了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我不会编程555

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值