How do I make a defaultdict safe for unexpecting clients?

后端 未结 5 2104
情话喂你
情话喂你 2021-01-05 15:00

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

相关标签:
5条回答
  • 2021-01-05 15:03

    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".

    0 讨论(0)
  • 2021-01-05 15:09

    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]})
    
    0 讨论(0)
  • 2021-01-05 15:14

    use different idiom:

    if 'key' not in d:
        print "Sorry, no dice!"
    
    0 讨论(0)
  • 2021-01-05 15:20

    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.

    0 讨论(0)
  • 2021-01-05 15:26

    You may still convert it to an normal dict.

    d = collections.defaultdict(list)
    d = dict(d)
    
    0 讨论(0)
提交回复
热议问题