我使用defaultdict(set)
在一个非常大的数据结构中填充内部Map。填充完后,整个结构(包括Map)将公开给客户端代码。在这一点上,我不希望任何人修改Map。
没有人会故意的。但有时候,客户端代码可能会意外地引用到一个不存在的元素。此时,一个普通的字典会产生KeyError
,但由于Map是defaultdict
,它只是在那个键上创建一个新元素(一个空集)。这是很难捕捉的,因为一切都是悄悄发生的。但是我需要确保这种情况不会发生(语义实际上不会中断,但是Map会变得很大)。
我该怎么办?我可以看到这些选择:
1.在当前和将来的客户端代码中找到所有对Map执行字典查找的示例,并将其转换为mapping.get(k, {})
。这太可怕了
1.在数据结构完全初始化后,通过将其转换为dict
来“冻结”defaultdict
。(我知道它并没有真正冻结,但我相信客户端代码实际上不会编写mapping[k] = v
。)不雅,和一个大的性能击中。
1.将defaultdict
Package 成dict
接口。有什么优雅的方法吗?但是我担心性能会受到很大的影响(这种查找在紧密循环中使用得很频繁)。
1.子类defaultdict
并添加一个方法,该方法“关闭”所有defaultdict
功能,使其表现得像常规dict
一样。它是上面3的变体,但我不确定它是否更快。如果不依赖于实现细节,我不知道它是否可行。
1.在数据结构中使用常规的dict
,重写所有代码,首先检查元素是否在字典中,如果不在,则添加它。不太好
3条答案
按热度按时间kzmpq1sx1#
defaultdict
文档对default_factory
说:如果default_factory属性为None,则会引发KeyError异常,并将key作为参数。
如果你只是将defaultdict的default_factory设置为
None
呢?例如,不知道这是否是最好的方法,但似乎有效。
qvtsj1bj2#
一旦你完成了你的defaultdict的填充,你可以简单地从它创建一个普通的dict:
如果默认dict是递归默认dict,请参阅this answer,它具有递归解决方案。
rmbxnbpk3#
你可以创建一个类,它包含对你的dict的引用,并防止setitem()