This seems to keep a consistent __init__ signature with OrderedDict (by .pop()-ing 'default_factory' from kwargs instead of specifying as a positionalkwarg):
def __init__(self, *a, **kw): default_factory = kw.pop('default_factory', self.__class__) OrderedDict.__init__(self, *a, **kw) self.default_factory = default_factory
def __missing__(self, key): self[key] = value = self.default_factory() return value
I've added a few tests (as well as to_json, and _repr_json_ https://gist.github.com/westurner/be22dba8110be099a35e/c1a3a7394e401d4742df0...
(Without this fix, json.loads(output_json, object_pairs_hook=OrderedDefaultDict) doesn't seem to work).
On Fri, Nov 13, 2015 at 11:17 PM, Andrew Barnert email@example.com wrote:
On Nov 13, 2015, at 20:46, Wes Turner firstname.lastname@example.org wrote:
On Fri, Oct 16, 2015 at 9:08 PM, Andrew Barnert via Python-ideas < email@example.com> wrote:
Actually, forget all that; it's even simpler.
At least in recent 3.x, the only thing wrong with inheriting from both types, assuming you put OrderedDict first, is the __init__ signature. So:
class OrderedDefaultDict(OrderedDict, defaultdict): def __init__(self, default_factory=None, *a, **kw): OrderedDict.__init__(self, *a, **kw) self.default_factory = default_factory
More importantly, because __missing__ support is built into dict, despite the confusing docs for defaultdict, you don't really need defaultdict at all here:
class OrderedDefaultDict(OrderedDict): def __init__(self, default_factory=None, *a, **kw): OrderedDict.__init__(self, *a, **kw) self.default_factory = default_factory def __missing__(self, key): self[key] = value = default_factory() return value
And either of these should work with 2.5+ (according to https://docs.python.org/2/library/stdtypes.html#dict that's when dict.__missing__ was added).
- [ ] Could/should maybe either of these make it into the standard library,
that would save a fair amount of copying.
You could say the same about everything in the recipes, every one-liner like "def identity(x): return x", and so on. But most such things aren't used that often, and there's a cost to putting them in the stdlib—more for people to learn and remember, more code to be maintained, bigger downloads, etc. So just saying "maybe it would save some copying" isn't an argument for adding it to the stdlib.
Adding OrderedDefaultDict as a docs recipe (as OrderedCounter already is) might be worth doing. Reorganizing the docs a bit to make it more obvious (by better highlighting __missing__, and making it clear that it's a method of dict rather than something special about defaultdict) seems even more likely to be worth it. If someone has an idea of how it should read, just file a docs bug and submit a patch and see if whoever's in charge of that area says it needs to come back here.
.. Great in combination w/ dict views: https://docs.python.org/2/library/stdtypes.html#dictionary-view-objects
Of course, and that works out of the box.