1

I have a nested dictionaries

root ={
  'user':{
    'Johnson':{
      'incoming':2000,
      'family'  :4,
      'play':None
    }
    'Smith':{
      'incoming':17000,
      'family'  :1,
      'play':False           
    }
  }
}

I can access any record but only with a lot of syntax: root['user']['Smith']['play']

I want to expand the syntax, somehow, to be able do like this:

print "Johnson incoming", root['/user/Johnson/incoming']
root['/user/Smith/play'] = True

Distinguishing from some potential duplicates:

Community
  • 1
  • 1
rth
  • 2,946
  • 1
  • 22
  • 27
  • I think your only option would be to write a function to do it, if you are open to the idea please tell me – Mohammad Ali Mar 05 '17 at 02:55
  • @MohammadAli Thanks, I did two functions `getroot('/user/Smith/play')` and `setroot('/user/Smith/play', True)` but I **want** something more elegant. – rth Mar 05 '17 at 02:58
  • well like you said you need functions, so my guess is that you think that your functions are not elegant. do you mind sharing your code. – parsethis Mar 05 '17 at 03:01
  • 2
    If you can live with the overheads you can subclass dict and override the `__getitem__` and `__setitem__` methods – Paul Panzer Mar 05 '17 at 03:02
  • @PaulPanzer Can you post an example of realization? – rth Mar 05 '17 at 03:03
  • Somebody else just posted something quite similar to what I had in mind. – Paul Panzer Mar 05 '17 at 03:05
  • @StephenRauch Xpath is function, which I try to avoid. Again, I **want** something elegant. My code is full of nested functions and I want to clean it up. – rth Mar 05 '17 at 03:17
  • Aside: Personally, I'm not sure that I agree with the idea that syntax is elegant and function calls are not. The most elegant language I can think of is Scheme -- it has almost no syntax, and *everything* is a function. – Charles Duffy Mar 05 '17 at 18:08

2 Answers2

4

How about something like this:

class Foo(dict):
    def __setitem__(self, key, value):
        parts = key.split('/', 1)
        if len(parts) == 2:
            if parts[0] not in self:
                self[parts[0]] = Foo()
            self[parts[0]].__setitem__(parts[1], value)
        else:
            super(Foo, self).__setitem__(key, value)

    def __getitem__(self, key):
        parts = key.split('/', 1)
        if len(parts) == 2:
            return self[parts[0]][parts[1]]
        else:
            return super(Foo, self).__getitem__(key)

You can use it like this:

In [8]: f = Foo()

In [9]: f['a/b/c'] = 10

In [10]: f['a/b/c']
Out[10]: 10
Oliver Dain
  • 9,617
  • 3
  • 35
  • 48
  • Perfect! Thank you! It is exactly what I looking fore – rth Mar 05 '17 at 03:05
  • 2
    Why don't you subclass dict directly? With your implementation `.keys()` and `.items()` and looping etc. won't work. – Paul Panzer Mar 05 '17 at 03:14
  • I agree with @PaulPanzer. My answer to this question is along the same thinking. – Sush Mar 05 '17 at 03:19
  • @PaulPanzer agreed. Update coming. – Oliver Dain Mar 05 '17 at 03:25
  • @PaulPanzer Is it possible to make a recursive class? so all sub dicts will be the objects of the same class. The top dict will remove first part of a key and call sub dict with rest of a key? – rth Mar 05 '17 at 03:32
  • @rth just updated my answer with something that inherits from `dict` and is recursive. `keys()`, `items()` etc. work as expected. – Oliver Dain Mar 05 '17 at 03:35
  • @rth you'd have to explicitly code that in the constructor but in principle it is possible. – Paul Panzer Mar 05 '17 at 03:36
0
root ={
  'user':{
    'Johnson':{
      'incoming':2000,
      'family'  :4,
      'play':None
    },
    'Smith':{
      'incoming':17000,
      'family'  :1,
      'play':False           
    }
  }
}


class myDict(dict):
    'my customer dictionary'
    def __setitem__(self, key, val):
        _, first, second, third = key.split('/')
        print first, second, third

        firstDict = self[first]
        secondDict = firstDict[second]
        dict.__setitem__(secondDict, third, val)




a = myDict(root)
print a
a['/user/Smith/play'] = 'hi there'
print a
Sush
  • 1,169
  • 1
  • 10
  • 26
  • I'm not sure I understand the question, is it to have an arbitrary depth for the 'root' dictionary? – Sush Mar 05 '17 at 03:20