Python 将'defaultdict'作为常规'dict'公开`
我使用Python 将'defaultdict'作为常规'dict'公开`,python,python-3.x,wrapper,defaultdict,Python,Python 3.x,Wrapper,Defaultdict,我使用defaultdict(set)在一个非常大的数据结构中填充一个内部映射。填充后,整个结构(包括映射)将暴露给客户机代码。在这一点上,我不希望任何人修改映射 没有人故意这么做。但有时,客户端代码可能会意外引用不存在的元素。此时,普通字典会引发KeyError,但由于映射是defaultdict,它只会在该键处创建一个新元素(空集)。这很难理解,因为一切都是无声的。但我需要确保这不会发生(语义实际上不会中断,但映射会增长到很大的规模) 我该怎么办?我可以看到这些选择: 在当前和将来的客户机代
defaultdict(set)
在一个非常大的数据结构中填充一个内部映射。填充后,整个结构(包括映射)将暴露给客户机代码。在这一点上,我不希望任何人修改映射
没有人故意这么做。但有时,客户端代码可能会意外引用不存在的元素。此时,普通字典会引发KeyError
,但由于映射是defaultdict
,它只会在该键处创建一个新元素(空集)。这很难理解,因为一切都是无声的。但我需要确保这不会发生(语义实际上不会中断,但映射会增长到很大的规模)
我该怎么办?我可以看到这些选择:
mapping.get(k,{})
。这太可怕了dict
“冻结”defaultdict
。(我知道它并没有真正冻结,但我相信客户端代码不会真的编写映射[k]=v
)不雅观,而且性能会受到很大影响defaultdict
包装到dict
界面中。这样做的优雅方式是什么?但是,我担心性能可能会受到巨大的影响(这种查找在紧密循环中大量使用)defaultdict
并添加一个方法,该方法“关闭”所有defaultdict
功能,使其表现为常规dict
。这是上面3的变体,但我不确定它是否更快。我不知道如果不依赖实现细节是否可行dict
,重写那里的所有代码,首先检查元素是否在字典中,如果不在,则添加它。不太好默认工厂
:
如果默认的_factory属性为None,则会引发KeyError
以键作为参数的异常
如果您只是将defaultdict的默认工厂设置为None
?例如:
>>> d = defaultdict(int)
>>> d['a'] += 1
>>> d
defaultdict(<type 'int'>, {'a': 1})
>>> d.default_factory = None
>>> d['b'] += 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'b'
>>>
>d=defaultdict(int)
>>>d['a']+=1
>>>d
defaultdict(,{'a':1})
>>>d.默认工厂=无
>>>d['b']+=2
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
键错误:“b”
>>>
不确定这是否是最好的方法,但似乎有效。您可以创建一个包含对dict的引用的类,并阻止setitem()
填充完defaultdict后,只需从中创建一个常规dict:
my_dict = dict(my_default_dict)
可以选择使用类型注释
如果默认dict是递归默认dict,请查看哪个使用递归解决方案。重写将只使用
dict.setdefault
方法。。。没什么大不了的deal@JBernardo你说的是选项4吗?关于defaultdict
我所知道的是,如果需要,它会覆盖\uu getitem\uuu
以添加元素。也许它使用setdefault
方法实现了这一点,也许它不调用setdefault
就直接实现了相同的逻辑。如果不依赖于实施细节,我不能做任何假设,对吗?他指的是你的选项#5。只需在代码中使用data.setdefault()来代替defaultdict,我认为您只需在defaultdict
上调用dict
来编辑就可以了it@inspectorG4dget数据结构的大小超过1 GB,因此复制所有数据(如果我调用dict
,就会发生这种情况)太贵了。谁知道我提出的解决方案已经作为defaultdict
的一个功能实现了呢?很好的发现。(+1)哇,这太完美了。我希望可以安全地更改现有的defaultdict
对象的default\u-factory
。@max--文档特别说明default\u-factory
是一个可写属性,所以应该是安全的。@max:使用源代码:,(名称、类型、偏移量、标志、doc;flags==0
表示它是可写的)如果它对关键方法使用纯python,那么它不是非常慢吗?对于getitem方法?我不确定与defaultdict的其他方法相比的性能开销,我认为Neal的解决方案最适合您的问题
my_dict = dict(my_default_dict)