Several times (even several in a row) I\'ve been bitten by the defaultdict bug: forgetting that something is actually a defaultdict and treating it like a regular dictionary
That is exactly the behavior you want from a defaultdict
and not a bug. If you dont't want it, dont use a defaultdict.
If you keep forgetting what type variables have, then name them appropriately - for example suffix your defaultdict names with "_ddict".
Using rkhayrov's idea of resetting self.default_factory
, here is a toggleable subclass of defaultdict
:
class ToggleableDefaultdict(collections.defaultdict):
def __init__(self,default_factory):
self._default_factory=default_factory
super(ToggleableDefaultdict,self).__init__(default_factory)
def off(self):
self.default_factory=None
def on(self):
self.default_factory=self._default_factory
For example:
d=ToggleableDefaultdict(list)
d['key'].append(1)
print(d)
# defaultdict(<type 'list'>, {'key': [1]})
d.off()
d['newkey'].append(2)
# KeyError: 'newkey'
d.on()
d['newkey'].append(2)
# defaultdict(<type 'list'>, {'newkey': [2], 'key': [1]})
use different idiom:
if 'key' not in d:
print "Sorry, no dice!"
You can prevent creation of default values by assigning d.default_factory = None
. However, I don't quite like the idea of object suddenly changing behavior. I'd prefer copying values to the new dict
unless it imposes severe performance penalty.
You may still convert it to an normal dict.
d = collections.defaultdict(list)
d = dict(d)