2007-09-18

 

Python Cookbook 4.19 向字典中添加项

需求:

你需要使用字典d,并使用d[k]的值,如果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)十分相似.它们之间基本的不同之处在于,假如k不是d中的一部分,setdefault会执行d[k]=v,然后再返回v,(get只返回v,而不会改变d的值).如果你即希望能像get一样取得字典中的值,又希望能适当的改变它,就使用setdefault.
对于d的value值是list的情况,setdefault显得特别有用.如本节演示的那样,最常用的写法就是:
somedict.setdefault(somekey, [  ]).append(somevalue)
对于不可修改值的情况,setdefault不是那么有用了,比如数字.如果你仅仅想统计数字的个数,比如单词数目,正确的方式是使用get,而不是setdefault:
theIndex[word] = theIndex.get(word, 0) + 1
因为你必然要重新绑定theIndex[word]变量(因为它是不可修改的),但对于我们的单词页码表的例子,你可不能像下面这样写:

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

最后一个版本的代码在每次执行的时候,使用了3个list,一个是[]做为参数,另一个包含pagenumber,最后一个包含N+1个元素.是由上面两个连接而成的.如此大量的使用列表必然会影响程序的效率.比如 ,在我的机器上,我统计了4个单词,每个都在1000页中的每页出现一次.以引用中的第一个版本为基准,try/except方法比它快10%,setdefault方法比它慢20%,在大多数的情况下,这点差异是可以忽略的.而get方法比它慢4倍,这样的效率差别是不可忽略的.

相关说明:

setdefault(...)
    D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D

Comments: 发表评论



<< Home

This page is powered by Blogger. Isn't yours?