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) 并且不必先担心用户名是否存在,因为如果不存在,它将成为一个键并且形成三个子键。

解决方法

您需要一个函数来创建您想要的结构,并将此函数作为参数传递给 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>,'key2': [2],'key3': []}})

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...