
Not the first time I found myself recently needing to create "multi-dimensional" dictionaries, so that I could write something like: my_dict = ['a']['b']['b']['a'] = 'fred' and once again I wonder why Python does not support that idiom directly, as it must be a fairly common requirement. I know that there are good solutions like the one at http://ohuiginn.net/mt/2010/07/nested_dictionaries_in_python.html or by using defaultdict but I feel that this really should be part of the language. So, should I propose a PEP? Thanks ... Richard

On Sun, Mar 30, 2014 at 2:36 AM, Richard Prosser <richard.prosser@mail.com> wrote:
Not the first time I found myself recently needing to create "multi-dimensional" dictionaries, so that I could write something like:
my_dict = ['a']['b']['b']['a'] = 'fred'
and once again I wonder why Python does not support that idiom directly, as it must be a fairly common requirement. I know that there are good solutions like the one at http://ohuiginn.net/mt/2010/07/nested_dictionaries_in_python.html or by using defaultdict but I feel that this really should be part of the language.
The NestedDict at the end of that blog post looks like a nice clean solution; and it's so short that it probably doesn't need to be in the standard library. But maybe that would make a handy example, if there's a place in the docs where you'd go looking for that sort of thing. Alternatively, you may find it simpler and easier to use a non-nested dictionary. I store persistent data for my MUD client in a structure like this: persist["window/downarr"] = blah blah Of course, this assumes your keys are simple strings, and it's best for literals; you can't easily iterate over "everything under window/", for instance. But if that covers your requirements, it's probably going to be easier to read and comprehend; and it'd probably be faster, too, although that shouldn't be a primary consideration. ChrisA

2014-03-29 16:46 GMT+01:00 Chris Angelico <rosuav@gmail.com>: Alternatively, you may find it simpler and easier to use a non-nested
dictionary. I store persistent data for my MUD client in a structure like this:
persist["window/downarr"] = blah blah
Of course, this assumes your keys are simple strings, and it's best for literals; you can't easily iterate over "everything under window/", for instance. But if that covers your requirements, it's probably going to be easier to read and comprehend; and it'd probably be faster, too, although that shouldn't be a primary consideration.
ChrisA
another possibility: use tuples as keys. persist['window', 'downarr'] = blah blah this works with all hashable types. PS: to elaborate for non-gurus: tuples in python are created by the comma, not the braces, so the above is another way to write persist[ ('window', 'downarr') ]

On Sat, Mar 29, 2014 at 03:36:06PM +0000, Richard Prosser wrote:
Not the first time I found myself recently needing to create "multi-dimensional" dictionaries, so that I could write something like:
my_dict = ['a']['b']['b']['a'] = 'fred'
Could you please explain what that is supposed to mean? I can't tell if that's supposed to be new syntax, or a typo. Did you mean this instead? mydict = {'a': {'b': {'b': {}}}} my_dict['a']['b']['b']['a'] = 'fred'
and once again I wonder why Python does not support that idiom directly,
It does. There are no special rules to learn, no special syntax to memorise, just the same dict syntax as you already know. You create a dict with {key: value}, and if the value itself is a dict, you just repeat the process with value --> {key: value}, as deeply as you need. Not every special case needs special syntax.
as it must be a fairly common requirement.
I doubt it. As the Zen of Python states, "Flat is better than nested". I think most people would try to avoid such deeply nested dicts if they can. I know I've never needed them.
I know that there are good solutions like the one at http://ohuiginn.net/mt/2010/07/nested_dictionaries_in_python.html or by using defaultdict but I feel that this really should be part of the language.
I don't think something like this should be encouraged, and besides it's a four-line solution: py> class MyDict(dict): ... def __missing__(self, key): ... t = self[key] = MyDict() ... return t ... py> x = MyDict() py> x[1]['a'][None][True][23.0] = "Surprise!" py> x {1: {'a': {None: {True: {23.0: 'Surprise!'}}}}}
So, should I propose a PEP?
No. Not every four-line utility class needs to be a built-in. -- Steven

On 2014-03-29, at 18:29 , Steven D'Aprano <steve@pearwood.info> wrote:
I know that there are good solutions like the one at http://ohuiginn.net/mt/2010/07/nested_dictionaries_in_python.html or by using defaultdict but I feel that this really should be part of the language.
I don't think something like this should be encouraged, and besides it's a four-line solution:
py> class MyDict(dict): ... def __missing__(self, key): ... t = self[key] = MyDict() ... return t ... py> x = MyDict() py> x[1]['a'][None][True][23.0] = "Surprise!" py> x {1: {'a': {None: {True: {23.0: 'Surprise!'}}}}}
In most case, a single line probably suffices: MyDict = lambda: collections.defaultdict(MyDict)

On 3/29/2014 11:36 AM, Richard Prosser wrote:
I know that there are good solutions like the one at http://ohuiginn.net/mt/2010/07/nested_dictionaries_in_python.html
You can file a request on the tracker asking that this simple 4-line example be added to the doc.
class NestedDict(dict): ... def __getitem__(self, key): ... if key in self: return self.get(key) ... return self.setdefault(key, NestedDict())
or by using defaultdict but I feel that this really should be part of the language.
It is. You just have to copy and paste ;-). Actually, I am being serious. The example is an application of dict.setdefault, which *is* in the language. -- Terry Jan Reedy
participants (7)
-
Chris Angelico
-
Greg Ewing
-
Masklinn
-
Philipp A.
-
Richard Prosser
-
Steven D'Aprano
-
Terry Reedy