首页 > 解决方案 > Defaultdict 自动为每个键创建一个子字典?

问题描述

我有一本字典,我经常在我的代码中做这样的事情:

special_dict = {}

# ...

if username not in special_dict:
    special_dict[username] = {}
    for subkey in ["Subkey1", "Subkey2", "Subkey3"]:
        special_dict[username][subkey] = []  # or {}, etc, depending on usecase

基本上我想要一个字典,其中对于每个用户名,值是另一个包含三个特定子键的字典,然后这些值是列表或集合或你有什么。

我熟悉 defaultdict 但我不确定如何在这里使“值类型”变得非常具体。通常,defaultdict(list)如果我希望每个值默认都是一个列表,我会这样做,但是有没有办法使默认值不是列表,而是本身是一种特定类型的字典?

理想情况下,最终我想要做的是special_dict[username][subkey].append(item)不必担心用户名是否存在,因为如果不存在,它将成为一个键并形成三个子键。

标签: pythonpython-3.xdictionarydefaultdict

解决方案


你需要一个函数来创建你想要的结构,并将这个函数作为参数传递给defaultdict

from collections import defaultdict

def name_subdict():
    return {'key1':[], 'key2':set(), 'key3':{}}

mydict = defaultdict(name_subdict)

mydict['John']['key1'].append(1)
mydict['John']['key2'].add(2)
mydict['Jane']['key3'][10] = 20

print(mydict)
# defaultdict(<function name_subdict at 0x7fcaf81193a0>, 
# {'John': {'key1': [1], 'key2': {2}, 'key3': {}}, 
#  'Jane': {'key1': [], 'key2': set(), 'key3': {10: 20}}})

回答您的评论:是的,您可以传递要用于所有子项的数据类型,如mydict = name_subdict(list). 只有一个警告:defaultdict 的参数必须是一个不带参数的函数(或任何可调用的)。

因此,name_subdict(list)应该返回一个函数,该函数将依次创建结构。

代码将是:

from collections import defaultdict

def name_subdict(data_type):
    # data type must be a callable like list, set, dict...
    def subdict_creator():
        return {key:data_type() for key in ['key1', 'key2', 'key3']}
    return subdict_creator
    
my_list_dict = defaultdict(name_subdict(list))
my_set_dict = defaultdict(name_subdict(set))

my_list_dict['John']['key1'].append(1)
my_list_dict['John']['key2'].append(2)

my_set_dict['Jane']['key3'].add(10)

print(my_list_dict)
# defaultdict(<function name_subdict.<locals>.subdict_creator at 0x7fcadbf27b80>, 
# {'John': {'key1': [1], 'key2': [2], 'key3': []}})

print(my_set_dict)
# defaultdict(<function name_subdict.<locals>.subdict_creator at 0x7fcadbbf25e0>, 
# {'Jane': {'key1': set(), 'key2': set(), 'key3': {10}}})

推荐阅读