【发布时间】:2013-08-01 13:50:04
【问题描述】:
有很多很好的类似getattr()的函数用于解析嵌套字典结构,比如:
- Finding a key recursively in a dictionary
- Suppose I have a python dictionary , many nests
- https://gist.github.com/mittenchops/5664038
我想做一个并行的 setattr()。本质上,给定:
cmd = 'f[0].a'
val = 'whatever'
x = {"a":"stuff"}
我想生成一个我可以分配的函数:
x['f'][0]['a'] = val
或多或少,这将与以下方式相同:
setattr(x,'f[0].a',val)
屈服:
>>> x
{"a":"stuff","f":[{"a":"whatever"}]}
我现在叫它setByDot():
setByDot(x,'f[0].a',val)
这样做的一个问题是,如果中间的键不存在,则需要检查并制作中间键,如果它不存在——即,对于上述情况:
>>> x = {"a":"stuff"}
>>> x['f'][0]['a'] = val
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'f'
所以,你首先要做的是:
>>> x['f']=[{}]
>>> x
{'a': 'stuff', 'f': [{}]}
>>> x['f'][0]['a']=val
>>> x
{'a': 'stuff', 'f': [{'a': 'whatever'}]}
另一个是下一项是列表时的键控与下一项是字符串时的键控不同,即:
>>> x = {"a":"stuff"}
>>> x['f']=['']
>>> x['f'][0]['a']=val
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
...失败,因为分配的是空字符串而不是空字典。 null dict 将是 dict 中每个非列表的正确分配,直到最后一个 --- 这可能是一个列表或一个值。
@TokenMacGuy 在下面的 cmets 中指出的第二个问题是,当您必须创建一个不存在的列表时,您可能必须创建大量空白值。所以,
setattr(x,'f[10].a',val)
---可能意味着算法将不得不制作一个中间体,如:
>>> x['f']=[{},{},{},{},{},{},{},{},{},{},{}]
>>> x['f'][10]['a']=val
屈服
>>> x
{"a":"stuff","f":[{},{},{},{},{},{},{},{},{},{},{"a":"whatever"}]}
因此这是与 getter 关联的 setter...
>>> getByDot(x,"f[10].a")
"whatever"
更重要的是,中间体应该/不/覆盖已经存在的值。
以下是我到目前为止的垃圾想法 --- 我可以识别列表与 dicts 和其他数据类型,并在它们不存在的地方创建它们。但是,我没有看到(a)在哪里放置递归调用,或者(b)当我遍历列表时如何“构建”深层对象,以及(c)如何区分 /probing/ 我是当我到达堆栈的末尾时,我必须从 /setting/ 构造深层对象。
def setByDot(obj,ref,newval):
ref = ref.replace("[",".[")
cmd = ref.split('.')
numkeys = len(cmd)
count = 0
for c in cmd:
count = count+1
while count < numkeys:
if c.find("["):
idstart = c.find("[")
numend = c.find("]")
try:
deep = obj[int(idstart+1:numend-1)]
except:
obj[int(idstart+1:numend-1)] = []
deep = obj[int(idstart+1:numend-1)]
else:
try:
deep = obj[c]
except:
if obj[c] isinstance(dict):
obj[c] = {}
else:
obj[c] = ''
deep = obj[c]
setByDot(deep,c,newval)
这似乎很棘手,因为如果您正在制作占位符,您必须向前看以检查 /next/ 对象的类型,并且您必须向后看以构建路径.
更新
我最近也收到了this question 的回复,这可能是相关的或有帮助的。
【问题讨论】:
标签: python algorithm recursion nested setattr