首页 > 解决方案 > 动态构建 Python 字典不会返回所需的结果

问题描述

我正在尝试ResourcesBuilder在 Python 3.7 中编写一个类:

import json


class ResourcesBuilder:
    def __init__(self):
        self.parent_account = {}
        self.accounts = {}

    def build(self, parent_account, child_account, service, data):
        self.parent_account[child_account] = {service: data}
        self.accounts[parent_account] = self.parent_account


def main():
    accounts = json.loads('{"p_acc_1": ["c_acc_1a", "c_acc_1b"], "p_acc_2": ["c_acc_2a", "c_acc_2b"]}')
    service = 'test_service'
    builder = ResourcesBuilder()
    for parent_account in accounts:
        for a_account in accounts[parent_account]:
            data = 'test_data'
            builder.build(parent_account, a_account, service, data)
    print(json.dumps(builder.accounts, indent=4, sort_keys=True))


if __name__ == "__main__":
    main()

运行时,上面的代码当前返回:

## CURRENT OUTCOME
{
    "p_acc_1": {
        "c_acc_1a": {
            "test_service": "test_data"
        },
        "c_acc_1b": {
            "test_service": "test_data"
        },
        "c_acc_2a": {
            "test_service": "test_data"    <--- this should not be returned
        },
        "c_acc_2b": {
            "test_service": "test_data"    <--- this should not be returned
        }
    },
    "p_acc_2": {
        "c_acc_1a": {
            "test_service": "test_data"    <--- this should not be returned
        },
        "c_acc_1b": {
            "test_service": "test_data"    <--- this should not be returned
        },
        "c_acc_2a": {
            "test_service": "test_data"
        },
        "c_acc_2b": {
            "test_service": "test_data"
        }
    }
}

如您所见,它列出了所有父帐户下的所有子帐户,而不是在其各自帐户下列出子帐户:

# DESIRED OUTCOME
{
    "p_acc_1": {
        "c_acc_1a": {
            "test_service": "test_data"
        },
        "c_acc_1b": {
            "test_service": "test_data"
        }
    },
    "p_acc_2": {
        "c_acc_2a": {
            "test_service": "test_data"
        },
        "c_acc_2b": {
            "test_service": "test_data"
        }
    }
}

我从 python 开始,所以我真的很感激我如何更好地实现我的目标。

标签: pythonjsonpython-3.xdictionary

解决方案


基本上,在您的功能的第二步中,您build实际上是将您创建的整个字典链接回帐户。您只需复制您为其分配的父级的子级词典self.accounts[parent_account]。由于在for子列表的循环中,您无法一次显式获取所有子数据,因此您需要创建一个新函数来链接父字典。

import json


class ResourcesBuilder:
    def __init__(self):
        self.parent_account = {}
        self.accounts = {}

    def build(self, parent_account, child_account, service, data):
        self.parent_account[child_account] = {service: data}

    # This function links the parent correctly
    # i.e., link only those dictionaries which are children of the
    # current parent
    def link_parent(self, parent_account, child_list):
        self.accounts[parent_account] = {k: self.parent_account[k] 
                                         for k in child_list}


def main():
    accounts = json.loads('{"p_acc_1": ["c_acc_1a", "c_acc_1b"], "p_acc_2": ["c_acc_2a", "c_acc_2b"]}')
    service = 'test_service'
    builder = ResourcesBuilder()
    for parent_account in accounts:
        for a_account in accounts[parent_account]:
            data = 'test_data'
            builder.build(parent_account, a_account, service, data)

        # Now once the children nodes have been created, link the parent
        builder.link_parent(parent_account, accounts[parent_account])
    print(json.dumps(builder.accounts, indent=4, sort_keys=True))


if __name__ == "__main__":
    main()

您可以参考这个带有工作代码的Google Colab 笔记本以获取更多信息。


推荐阅读