为不存在的对象属性赋值
Assigning values to objects attributes that don't exist
我正在使用 python(2.7) 进行数据挖掘作业。我为所有单词(类别中存在的单词)创建了一个权重字典,对于这个字典中不存在的单词,我想分配一个默认值。
首先我在使用它之前尝试为每个键设置默认值,它工作得很好,但不知何故我认为它看起来不那么 pythonic。因此我尝试使用 defaultdict,它在大多数情况下工作得很好。但是,有时它 returns 是一个不正确的值。一开始我以为可能是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) 快吗?
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)
显然,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 中的工作原理。
这不是 defaultdict
的用例。
相反,只需使用 get
从字典中获取值。
val = dict.get("doesnotexist", 1234321)
完全可以接受 python "get" 有第二个参数,如果找不到密钥,则为默认值。
如果您只为 "get" 需要这个,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]
应该returnvar=2
的当前值。它在初始化时没有被替换到字典中,但表现得就像你在这个位置定义了一个函数,访问 "outer" 变量 var.
黑客是这样的:
def constfunc(x):
return lambda: x
ex3 = defaultdict(constfunc(var))
现在 constfunc 在初始化时计算,x 是调用的局部变量,lambda 现在将 return 一个 x 不再改变。我想你可以内联这个(未经测试):
ex3 = defaultdict((lambda x: lambda: x)(var))
看,Python 的魔力,捕获 "closures" 和命令式语言假装进行函数式编程的异常。
我正在使用 python(2.7) 进行数据挖掘作业。我为所有单词(类别中存在的单词)创建了一个权重字典,对于这个字典中不存在的单词,我想分配一个默认值。 首先我在使用它之前尝试为每个键设置默认值,它工作得很好,但不知何故我认为它看起来不那么 pythonic。因此我尝试使用 defaultdict,它在大多数情况下工作得很好。但是,有时它 returns 是一个不正确的值。一开始我以为可能是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) 快吗?
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)
显然,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 中的工作原理。
这不是 defaultdict
的用例。
相反,只需使用 get
从字典中获取值。
val = dict.get("doesnotexist", 1234321)
完全可以接受 python "get" 有第二个参数,如果找不到密钥,则为默认值。
如果您只为 "get" 需要这个,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]
应该returnvar=2
的当前值。它在初始化时没有被替换到字典中,但表现得就像你在这个位置定义了一个函数,访问 "outer" 变量 var.
黑客是这样的:
def constfunc(x):
return lambda: x
ex3 = defaultdict(constfunc(var))
现在 constfunc 在初始化时计算,x 是调用的局部变量,lambda 现在将 return 一个 x 不再改变。我想你可以内联这个(未经测试):
ex3 = defaultdict((lambda x: lambda: x)(var))
看,Python 的魔力,捕获 "closures" 和命令式语言假装进行函数式编程的异常。