首页 > 解决方案 > 向嵌套字典中的内部字典添加新元素

问题描述

我正在使用 Python 3.6.4。我正在尝试创建一个由多个进程共享的嵌套字典,并根据各种函数的结果将键值对添加到内部字典中。

下面是我的代码示例。

manager = Manager()
scores = manager.dict()

def add_scores(name, game):
    global scores
    if name not in scores:
        scores[name] = {}
    if game in scores[name]:
        scores[name][game] += 1
    else:
        scores[name] = {game: 1}

填充字典的示例是

scores = { 'John': {'golf': '1', 'football': '2'}, 
           'Alice': {'basketball': '1', 'football': '3', 'tennis': 2}}

各种游戏都有函数,根据这些函数的结果,将为每个人创建一个键值对。

我知道这条线scores[name] = {game: 1}有问题,因为它只是scores[name]用最后一场比赛覆盖了字典。

我也试过下面的代码。

manager = Manager()
scores = manager.dict()

def add_scores(name, game):
    global scores
    if name not in scores:
        scores[name] = {}
    try:
        scores[name][game] += 1
    except Exception as e:
        print(e)

在这种情况下,print(e)给我game价值观。如果我scores[name][game] = 1只是用来测试,没有错误,但字典是空的,例如{'John': {}, 'Alice': {}}. 我似乎无法简单地通过为该键分配一个值来向字典添加新键。

如何添加到字典中?

标签: pythondictionary

解决方案


关键是要记住Manager.dict只会在setitem期间同步。如果您直接编辑值对象,Manager.dict将看不到更改,因此不会同步。(因为从Manager.dict的角度来看,key 仍然指向同一个值对象;Manager.dict不监视指向的值对象内部的变化。)

这是在 Python 3.9 和 Python 3.6(以及介于两者之间的每个 Python 版本)中运行的版本:

from multiprocessing import Process, Manager


def add_scores(_scores, name, game):
    # First get the inner dict
    # No need to use .setdefault() because we're going to
    # overwrite the value later, anyways
    nmgm = _scores.get(name, {})
    # Modify it
    nmgm[game] = nmgm.get(game, 0) + 1
    # Write it back so Manager.dict will sync
    _scores[name] = nmgm


players = {
    "Alex": ["Soccer", "Soccer", "Tennis"], 
    "Bob": ["Tennis", "Quidditch", "Soccer", "Tennis"]
    }


if __name__ == '__main__':
    manager = Manager()
    scores = manager.dict()

    for iplayer, games in players.items():
        for igame in games:
            p = Process(target=add_scores, args=(scores, iplayer, igame))
            p.start()
            p.join()

    print(scores)

请注意,我不使用global,而是将实例传递Manager.dict给工作进程。在我的 Python 安装中,初始化manager和结构scores之外的__main__结果是RuntimeError.

结果:

{'Alex': {'Soccer': 2, 'Tennis': 1}, 'Bob': {'Tennis': 2, 'Quidditch': 1, 'Soccer': 1}}

推荐阅读