创建一个智能函数从字典列表中提取值



我有一个类似的数据列表

data = [
{
"name": "Box 0",
"type": "Box",
"vals": {
"corner1": "0,0,0",
"corner2": "0,0,5",
"rotate": "0",
"scale": "1",
"translate": "0,0,0"
}
},
{
"name": "Ovus 1",
"type": "Ovus",
"vals": {
"radiusb": "1",
"radiust": "0.5",
"rotate": "0",
"scale": "1",
"translate": "0,0,0"
}
}
]

我想创建一个表单的函数

fetch_attributes(name, key)

其中我可以给出关键属性值类型、vals或scale。

我的问题是scale属性在vals字典中。我能让函数在我给出key=type时给我类型吗?当我要求key=scale,它会自动进入vals字典。

我的方法

我使用此代码作为name="Box 0"的示例

obj = [i for i in data if i['name'] == name][0]
key_1 = "['vals']" # If I want complete dict of vals
key_2 = "['vals']['scale']" #If I want only one val out of vals
key_3 = "['type']" # If I want type
result_1 = eval('obj' + key_1)
result_2 = eval('obj' + key_2)
result_3 = eval('obj' + key_3)

我想知道是否有更好或更像蟒蛇的方式来完成这项任务

编辑

我想要一种方法,它也将帮助或指导创建一个edit_attributes函数作为

edit_attributes(name, key, value)

我认为这(现在(符合您的要求:

def fetch_attributes(data, name, key):
for dct in data:
if dct['name'] == name:
obj = dct
break
else:
raise KeyError(f'No object with name {name!r} in data')
if isinstance(obj, dict):
if key in obj:
return obj[key]
for value in obj.values():
if isinstance(value, dict):  # Nested dict?
if key in value:
return value[key]
raise KeyError(f'{key!r} not in data')

print(fetch_attributes(data, 'Box 0', 'vals'))   # -> {'corner1': '0,0,0', 'corner2': '0,0,5', 'rotate': '0', 'scale': '1', 'translate': '0,0,0'}
print(fetch_attributes(data, 'Box 0', 'scale'))  # -> 1
print(fetch_attributes(data, 'Box 0', 'type'))   # -> Box

这应该适用于任何级别的字典嵌套。

def find(obj, key):
if key not in obj:
for k in obj.keys():
if type(obj[k]) == type({}):
return find(obj[k], key)
else:
return obj[key]
return None
def fetch_attributes(name, key):
obj = [i for i in data if i['name'] == name][0]
return find(obj, key)

但是,如果obj = [i for i in data if i['name'] == name][0]返回多个值,那么您也需要一个for循环。

当找不到属性名称时,可以利用字典的get((函数的第二个参数级联到子字典中:

def getProp(d,key): return d.get(key,d["vals"].get(key,None))

输出:

for d in data:
print([ getProp(d,"name"),getProp(d,"type"),getProp(d,"scale") ])
# ['Box 0', 'Box', '1']
# ['Ovus 1', 'Ovus', '1']

赋值会稍微复杂一些,但也可以使用setdefault((:

def setProp(d,key,value):
[d,d.setdefault("vals",dict())][key=="vals"][key] = value

最新更新