将python字典路径作为变量发送



这个或类似的问题过去可能被问过,但我找不到适合我的情况的解决方案。我目前有以下格言:

my_dict = {
"test": [
{
"inner_test": [
{
"name": "Jack"
},
{
"name": "Ann"
}
]
},
{
"inner_test": [
{
"name": "David"
},
{
"name": "Danny"
}
],
"some_test": [
3,
[
{
"name": "Benny"
},
{
"name": "Ann"
}
]
]
}
]
}

我使用自定义python库来获取特定密钥的路径(我不知道嵌套深度也不知道密钥的位置(,例如,我想获取第一个"Ann"值的路径,这样变量将包含

test_var = ['test',0,'inner_test',1,'name']

下一步,我想将另一个键+值添加到代码中,作为我之前找到的路径的同级,例如-

test_var_2 = test_var[:-1]

所以现在test_var_2 = ['test',0,'inner_test',1]

我的问题是,如何将test_var_2作为路径变量发送,而不是发送

`my_dict['test',0,'inner_test',1]`

例如,如果我想添加另一个密钥,值对,如-

my_dict['test',0,'inner_test',1, 'country'] = 'a_country'

但是这样发送:

my_dict[test_var_2] = 'a_country'

我尝试将test_var_2转换为元组,但出现"密钥错误"此外,我尝试使用这个库-https://pypi.org/project/dict-deep/也无济于事。谢谢:(

如何将test_var_2作为路径变量发送

编写一个函数来迭代地处理路径

# - this one is recursive
def f(vars,d):
if not vars:
return d
d = d[vars[0]]
return f(vars[1:],d)
# - "normal" iteration
def g(vars,d):
vars = iter(vars)
val = d[next(vars)]
for item in vars:
val = val[item]
return val

>>>f(test_var_2,my_dict)
{'name': 'Ann'}

然后您可以制作一个特定于字典的偏函数。

import functools
mydict_pathfinder = functools.partial(f,d=my_dict)
#mydict_pathfinder(test_var_2)

或者特定于通过任何类似结构字典的路径:

q = functools.partial(f,test_var_2)
#q(my_dict)

您可以使用operator.itemgetter为每个路径创建一个可调用的,然后组合这些可调用的。生成特定于路径的可调用项。

import operator
path = [operator.itemgetter(item) for item in test_var_2]
def compose(funcs):
def wrapped(d):
func = funcs[0](d)
for f in funcs[1:]:
func = f(func)
return func
return wrapped
pathfinder = compose(path)
#pathfinder(my_dict)

添加另一个密钥,值

获取dict并更新它。

>>> target = g(test_var_2,my_dict)
>>> target.update({'foo':'bar'})
>>> from pprint import pprint
>>> pprint(my_dict)
{'test': [{'inner_test': [{'name': 'Jack'}, {'foo': 'bar', 'name': 'Ann'}]},
{'inner_test': [{'name': 'David'}, {'name': 'Danny'}],
'some_test': [3, [{'name': 'Benny'}, {'name': 'Ann'}]]}]}
>>> g(test_var_2,my_dict).update({'another':'one'})
>>> pprint(my_dict)
{'test': [{'inner_test': [{'name': 'Jack'},
{'another': 'one', 'foo': 'bar', 'name': 'Ann'}]},
{'inner_test': [{'name': 'David'}, {'name': 'Danny'}],
'some_test': [3, [{'name': 'Benny'}, {'name': 'Ann'}]]}]}

>>> pathfinder(my_dict).update({999:000})
>>> pathfinder(my_dict).update({'x':'y'})
>>>pprint(my_dict)
{'test': [{'inner_test': [{'name': 'Jack'}, {999: 0, 'name': 'Ann', 'x': 'y'}]},
{'inner_test': [{'name': 'David'}, {'name': 'Danny'}],
'some_test': [3, [{'name': 'Benny'}, {'name': 'Ann'}]]}]}

如果你想使用订阅-my_dict[test_var_2].update({'new':'item'}),你必须用__getitem__方法编写一个类,该方法使用类似于上面显示的过程迭代地遍历字典。有点像。

class Pathfinder:
def __init__(self,d):
self.d = d
def __getitem__(self,item):
# use any of the functions above
return f(item)
pf = Pathfinder(my_dict)
>>> pf[test_var_2].update({'did it':'work?'})
>>> pprint(my_dict)
{'test': [{'inner_test': [{'name': 'Jack'},
{'did it': 'work?', 'name': 'Ann'}]},
{'inner_test': [{'name': 'David'}, {'name': 'Danny'}],
'some_test': [3, [{'name': 'Benny'}, {'name': 'Ann'}]]}]}

最新更新