如何使用递归方法更新python字典
Posted
技术标签:
【中文标题】如何使用递归方法更新python字典【英文标题】:How to use recursive method to update python dictionaries 【发布时间】:2021-12-30 23:58:08 【问题描述】:我正在使用 Python zeep 发出 SOAP 请求。据我所知,zeep 可以使用字典作为输入来提出请求。
由于我正在使用多种方法,因此我想创建一个通用函数来接收参数及其在方法的 WSDL 中定义的相应层次结构,并构造 request_data_dictionary,考虑到它可能包含嵌套数据,它可能非常复杂。
在定义我的参数时,我给了他们一个级别属性,以了解该参数在请求数据字典中的深度。而且我确信参数是按顺序处理的。
我的测试用例具有以下结构。我有 4 个参数:par1、par2、par3 和 par4。每个参数都是编号较小的参数的子参数,因此 par2 是 par1 的子参数,依此类推。我需要的数据输出形式如下:
'par0': 'par1': 'par2': 'par3': 'par4': False
如果我添加一个 par2.1 作为 par1 的另一个孩子,字典应该有这种形式:
'par0': 'par1': 'par2.1': False, 'par2': 'par3': 'par4': False
所以我编写了以下函数来构造我的 request_dictionary:
def _prepare_request_dictionary(self):
data_dictionary =
for line in self.request_line_ids.sorted(key=lambda l: l.parameter_id.level):
parameter_name = line.parameter_id.name
parent_parameter_name = line.parameter_id.parent_id.name if line.parameter_id.parent_id else False
line_value = convert_value(line.value, line.parameter_type) if not line.parameter_id.is_compound and line.value else False
if line.parameter_id.level == 1 and parameter_name not in data_dictionary.keys():
data_dictionary[parameter_name] = line_value
elif line.parameter_id.level == 2:
if parent_parameter_name in data_dictionary.keys():
data_dictionary = if isinstance(data_dictionary[parent_parameter_name], dict):
data_dictionary[parent_parameter_name] = **data_dictionary[parent_parameter_name], **parameter_name: line_value
elif isinstance(data_dictionary[parent_parameter_name], list):
data_dictionary[parent_parameter_name].append(parameter_name: line_value)
elif data_dictionary[parent_parameter_name] is False:
data_dictionary[parent_parameter_name] = parameter_name: line_value
elif line.parameter_id.level == 3:
for value in data_dictionary.values():
if isinstance(value, dict):
if parent_parameter_name in value.keys():
if isinstance(value[parent_parameter_name], dict):
value[parent_parameter_name] = **value[parent_parameter_name], **parameter_name: line_value
elif isinstance(value[parent_parameter_name], list):
value[parent_parameter_name].append(parameter_name: line_value)
elif value[parent_parameter_name] is False:
value[parent_parameter_name] = parameter_name: line_value
elif line.parameter_id.level == 4:
for value in data_dictionary.values():
if isinstance(value, dict):
for sub_value in value.values():
if parent_parameter_name in sub_value.keys():
if isinstance(sub_value[parent_parameter_name], dict):
sub_value[parent_parameter_name] = **sub_value[parent_parameter_name], **parameter_name: line_value
elif isinstance(sub_value[parent_parameter_name], list):
sub_value[parent_parameter_name].append(parameter_name: line_value)
elif sub_value[parent_parameter_name] is False:
sub_value[parent_parameter_name] = parameter_name: line_value
elif line.parameter_id.level == 5:
for value in data_dictionary.values():
if isinstance(value, dict):
for sub_value in value.values():
if isinstance(sub_value, dict):
for sub_sub_value in sub_value.values():
if isinstance(sub_sub_value, dict):
if parent_parameter_name in sub_sub_value.keys():
if isinstance(sub_sub_value[parent_parameter_name], dict):
sub_sub_value[parent_parameter_name] = **sub_sub_value[parent_parameter_name], **parameter_name: line_value
elif isinstance(sub_sub_value[parent_parameter_name], list):
sub_sub_value[parent_parameter_name].append(parameter_name: line_value)
elif sub_sub_value[parent_parameter_name] is False:
sub_sub_value[parent_parameter_name] = parameter_name: line_value
return data_dictionary
如你所见,这个函数有一些重复的部分,如下所示:
if isinstance(value[parent_parameter_name], dict):
value[parent_parameter_name] = **value[parent_parameter_name], **parameter_name: line_value
elif isinstance(value[parent_parameter_name], list):
value[parent_parameter_name].append(parameter_name: line_value)
elif value[parent_parameter_name] is False:
value[parent_parameter_name] = parameter_name: line_value
还有这个:
for value in data_dictionary.values():
if isinstance(value, dict):
for sub_value in value.values():
if isinstance(sub_value, dict):
for sub_sub_value in sub_value.values():
if isinstance(sub_sub_value, dict):
所以我做了一个名为“update_data_dictionary”的子函数来模块化它:
def update_data_dictionary(work_dictionary, update_dictionary, parent_parameter):
if isinstance(work_dictionary[parent_parameter], dict):
work_dictionary[parent_parameter] = **work_dictionary[parent_parameter], **update_dictionary
elif isinstance(work_dictionary[parent_parameter], list):
work_dictionary[parent_parameter].append(update_dictionary)
elif work_dictionary[parent_parameter] is False:
work_dictionary[parent_parameter] = update_dictionary
return work_dictionary
问题是我不知道如何在第 3 级再次使用此方法,因为函数“update_data_dictionary”返回一个无法替换值的字典。
我知道这可以通过递归函数来解决,如果有人可以帮助我将这个递归函数变成一个无限级别的递归函数,我将不胜感激。
【问题讨论】:
你能给出一个数据例子和一个你想要构建的具有理想结构的字典的例子吗?目前很难理解你的代码做了什么以及你想要实现什么。 嗨,我编辑以更好地解释我想要的字典应该如何输出。我没有提到的是我正在使用 Odoo 并且 request_line_ids 变量是我使用参数创建的模型的记录集。 【参考方案1】:我花了一些时间,但我能够创建我需要的递归方法,它具有以下形式:
def update_data_dictionary(work_dictionary, line_value, parameter, work_level=0, sub_dictionary=None):
parameter_name = parameter.name
parent_parameter = parameter.parent_id.name
parent_level = parameter.parent_id.level
level = 1 if work_level == 0 else work_level
update_dictionary = sub_dictionary if sub_dictionary else parameter_name: line_value
if parent_level == level:
if parent_parameter in work_dictionary.keys():
if isinstance(work_dictionary[parent_parameter], dict):
work_dictionary[parent_parameter] = **work_dictionary[parent_parameter], **update_dictionary
elif work_dictionary[parent_parameter] is False:
work_dictionary[parent_parameter] = update_dictionary
else:
for value in work_dictionary.copy().values():
if isinstance(value, dict):
processed_dictionary = update_data_dictionary(value, line_value, parameter, (level+1), update_dictionary)
return work_dictionary
此方法更新任何级别中的任何子参数的内容,只要参数的级别及其父级层次结构定义良好。
【讨论】:
以上是关于如何使用递归方法更新python字典的主要内容,如果未能解决你的问题,请参考以下文章