13

After reading this question, I noticed that S. Lott might have liked to use an “ordered defaultdict”, but it doesn't exist. Now, I wonder: Why do we have so many dict classes in Python?

  • dict
  • blist.sorteddict
  • collections.OrderedDict
  • collections.defaultdict
  • weakref.WeakKeyDictionary
  • weakref.WeakValueDictionary
  • others?

Why not have something like this,

dict(initializer=[], sorted=False, ordered=False, default=None, 
     weak_keys=False, weak_values=False)

that unifies everything, and provides every useful combination?

Community
  • 1
  • 1
Neil G
  • 32,138
  • 39
  • 156
  • 257
  • Then what happens when you use `a = {}`? – GWW Jul 06 '11 at 20:53
  • 2
    `{}` should default construct a regular dict? – Neil G Jul 06 '11 at 20:53
  • I think he means, to get at the other forms of dict we use the `dict()` initialisation he described – Jakob Bowyer Jul 06 '11 at 20:54
  • I suppose that makes sense it's an interesting question – GWW Jul 06 '11 at 20:54
  • 2
    I like the idea, I wonder what would be the behaviour in cases where sorted=True and weak_keys=True – fabrizioM Jul 06 '11 at 20:54
  • @Neil G: "S. Lott would have liked to use an “ordered defaultdict”. Not really. I saw no reason for considering order at all. – S.Lott Jul 06 '11 at 20:55
  • 2
    @Neil G: "Every Combination"? Really? Even future combinations that haven't been invented yet? – S.Lott Jul 06 '11 at 20:55
  • @S.Lott: I know you said you didn't consider it, but if it were part of the requirement, then your beautiful solution couldn't be used. The `groupby` solution below yours is far uglier. – Neil G Jul 06 '11 at 20:56
  • @fabrizioM: considering the restriction you mention and that sorted+ordered doesn't make sense, there are 20 possibilities (of which 6 are readily accessible today.) – Neil G Jul 06 '11 at 21:18

4 Answers4

12

One issue is that making this change would break backward-compatibility, due to this type of constructor usage that exists now:

>>> dict(one=1, two=2)
{'two': 2, 'one': 1}
FogleBird
  • 74,300
  • 25
  • 125
  • 131
  • I don't think this is a good reason. If having a single `dict` class was a good idea apart from backward compatibility, it would have been mooted for Python 3. – RoundTower Jul 06 '11 at 23:08
8

Those extra options don't come for free. Since 99.9% of Python is built on dict, it is very important to make it as minimal and fast as possible.

Blender
  • 289,723
  • 53
  • 439
  • 496
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • 1
    Can't `__new__` be overridden so that the `dict` constructor returns the regular, lightweight `dict` class if all the other options are `False`/`None`? – Neil G Jul 06 '11 at 20:58
  • How often are the other options likely to *not* be `False`/`None`? – Ignacio Vazquez-Abrams Jul 06 '11 at 20:59
  • 1
    The trouble is that with a problem like the linked problem, it's the combinations (like ordered defaultdict) you want that aren't available at all. Also, I didn't know about all of these other dicts when I first started learning Python, and they would have been much more discoverable as options to the standard dict rather than tucked away in libraries that I had to find out about. – Neil G Jul 06 '11 at 21:03
4

Because the implementations differ a lot. You'd basically end up with a dict factory that returns an instance of a _dict(A very fast, low-overhead dictionary - the current dict), ordereddict, defaultdict, ... class. Also, you could not initialize dictionaries with keyword arguments anymore; programs relying on this would fail:

>>> dict(sorted=42)
{'sorted': 42}
# Your proposal would lead to an empty dictionary here (breaking compatibility)

Besides, when it's reasonable, the various classes already inherit from each other:

>>> collections.defaultdict.__bases__
(<type 'dict'>,)
phihag
  • 278,196
  • 72
  • 453
  • 469
0

This is why languages have "mixins".

You could try to invent something like the following by defining the right bunch of classes.

class defaultdict( dict, unordered, default_init ): pass
class OrderedDict( dict, ordered, nodefault_init ): pass
class WeakKeyDict( dict, ordered, nodefault_init, weakkey ): pass
class KeyValueDict( dict, ordered, nodefault_init, weakvalue ): pass

Then, once you have those "unified" dictionaries, your applications look like this

groups= defaultdict( list )

No real change to the app, is there?

S.Lott
  • 384,516
  • 81
  • 508
  • 779