views:

163

answers:

2

This question is about implementing the full Perl autovivification in python. I know similar questions were asked before and so far the best answre is http://stackoverflow.com/questions/635483/what-is-the-best-way-to-implement-nested-dictionaries-in-python/652284#652284. However, I'm looking to do this:

a['x']['y'].append('z')

without declaring a['x']['y'] = [] first, or rather, not declaring a['x'] = {} either. (Note in Perl you can do push @{$a->{x}{y}}, 'z';.) I know dict and list classes sorta don't mix so this is hard, but I'm interested in seeing if someone has an ingenius solution probably involving creating an inherited class from dict but defined a new append method on it? I also know this might throw off some python purists who will ask me to stick with Perl. But even just for a challenge, I'd like to see something. thx!

+6  A: 
a = collections.defaultdict(lambda: collections.defaultdict(list))
Ignacio Vazquez-Abrams
Beautiful solution. Thank you very much.
Zhang18
An example of python having one, and only one, obvious way to do something :)
Brian
Actually I realized this answer only works for 2 levels of dict and a 3rd level of list. Is there a way to be level-agnostic? i.e., after declaring a, I can do either `a['x'].append('z')` or `a['x']['y']['w'].append('z')`? Thx.
Zhang18
Not with the anything in the stdlib. It is possible to do via creating your own class that implements `__getitem__()` et alia since `dict` does not support the `append()` method, and `list` only supports integer indexes.
Ignacio Vazquez-Abrams
So do you have an example of how I'd go about doing that? Appreciate it.
Zhang18
Can anyone give a tried-and-true example of how to create a class per Ignacio's suggestion? Thx.
Zhang18
+1  A: 

Perhaps this solves your need for any number of “dimensions” in your dictionary:

a= collections.defaultdict(list)

the only change in your code being:

a['x', 'y'].append('z')

Of course, this solution being the one you want depends on two conditions:

  1. whether you need to easily access all lists with e.g. 'x' in the “first dimension“
  2. whether you are stuck to the way Perl magically pleases you more :)

If either of these two conditions is true, my solution won't help you.

ΤΖΩΤΖΙΟΥ
Yes for 1. and Yes for 2, unfortunately. So I'll have to live with the fact that there is no analogy in Python for Perl in this case - kinda dissapointing.
Zhang18
Imagine you're dating, don't know, Nicole Kidman. You tell her that it's kind of disappointing she doesn't have the curves of, say, Monica Bellucci. Can you begin to fathom the lack of usefulness (and grace!) of such a statement? Anyway, parables aside, ISTM that you made your point, and the world can finally exhale.
ΤΖΩΤΖΙΟΥ