我正在使用python(2.7)进行数据挖掘作业。我为所有单词(存在于类别中)创建了一个权重dict,对于此dict中不存在的单词,我创建了,我想指定一个默认值。 首先我在使用它之前尝试使用setdefault for everykey,它工作得很好,但不知怎的,我觉得它看起来并不那么pythonic。因此我尝试使用defaultdict,它在大多数情况下工作得很好。但是,有时它返回的值不正确。首先我认为它可能是由 defaultdict 或lambda函数引起的,但显然没有错误。
for node in globalTreeRoot.traverse():
...irrelevant...
weight_dict = {.......}
default_value = 1.0 / (totalwords + dictlen)
node.default_value = 1.0/ (totalwords + dictlen)
......
node.weight_dict_ori = weight_dict
node.weight_dict = defaultdict(lambda :default_value,weight_dict)
因此,当我尝试打印循环期间不存在的值时,它会给我一个正确的值。但是,在代码完成运行后,当我尝试:
print node.weight_dict["doesnotexist"],
它给了我一个不正确的值,当错误时通常是一个与其他节点相关的值。我尝试搜索 python命名系统或动态地为对象属性赋值,但是没有想出来。
顺便说一下, defaultdict 比每次使用setdefault(k,v)更快?
答案 0 :(得分:1)
这不是defaultdict
的用例。
相反,只需使用get
从字典中获取值。
val = dict.get("doesnotexist", 1234321)
是完全可以接受的python" get"有第二个参数,如果找不到键,则为默认值。
如果您只需要#34; get&#34 ;,则defaultdict有点矫枉过正。它意味着像这样使用:
example = defaultdict(list)
example[key].append(1)
每次都不必显式初始化键列表组合。对于数值,改进是微不足道的:
ex1, ex2 = dict, defaultdict(lambda: 0)
ex1[key] = ex1.get(key, 0) + 1
ex2[key] += 1
您原来的问题可能是因为您重复使用了存储重量的变量。确保它是循环的本地!
var = 1
ex3 = defaultdict(lambda: var)
var = 2
print ex3[123]
应该返回 var=2
的当前值。它在初始化时没有被代入字典,但表现得好像你已经在这个位置定义了一个函数,访问了"外部"变量变种
黑客就是这样:
def constfunc(x):
return lambda: x
ex3 = defaultdict(constfunc(var))
现在constfunc在初始化时被计算,x是调用的局部变量,而lambda现在将返回一个不再变化的x。我想你可以内联这个(未经测试):
ex3 = defaultdict((lambda x: lambda: x)(var))
看,Python的魔力,捕获"关闭"假装进行函数式编程的命令式语言的异常。
答案 1 :(得分:0)
setdefault
绝对是您应该用来设置默认值的。
for node in globalTreeRoot.traverse():
node.default_value = 1.0 / (totalwords + dictlen)
node.weight_dict = {}
# if you did want to use a defaultdict here for some reason, it would be
# node.weight_dict = defaultdict(lambda: node.default_value)
for word in wordlist:
value = node.weight_dict.setdefault(word, node.default_value)
答案 2 :(得分:0)
显然,defaultdict有问题。
d1 = {"a":10,"b":9,"c":8}
seven = 7
d2 = defaultdict(lambda :seven,d1)
seven = 8
d3 = defaultdict(lambda :seven,d1)
结果:
>>> d2[4234]
8
我仍然不明白为什么会这样。至于我的工作,我会坚持使用 setdefault 。
更新: 谢谢回答。我误解了变量作用域在Python中是如何工作的。