magical expanding hash

James Stroud jstroud at
Tue Jan 17 21:28:02 EST 2006

braver wrote:
> Thanks, James!  This is really helpful.
> : It would take a lot of coding to make that << work right. Better is
> the pythonic
> :
> : m[key] = [value]
> :
> : Its really only one more keystroke than
> :
> : m[key] << value
> But it's only for the first element, right?  I'd have to say
> meh[key1]...[keyN].append(elem2) after that, while I want an operator
> to look the same.

Yes, being explicit is only for the first element with the "<<". If you 
use the lshiftinglist I provided, you could easily do

class lshiftinglist(list):
   def __lshift__(self, value):
     list.append(self, value)

class meh(dict):
   def __getitem__(self, item):
     return dict.setdefault(self, item, meh())
   def __getattr__(self, attr):
   def __lshift__(self, value):
     print "You are thinking of '%s'." % value
   def __iadd__(self, other):
     # don't try this on a populated meh!!!!!
     return other

m = meh()

m['fred'] = lshiftinglist([18])
m['fred'] << 25
m['barney'] += 1
m['barney'] += 1

print m  # {'barney': 2, 'fred': [18, 25]}

And so-on. More pythonic, of course is

m['fred'] = [18]
m['barney'] = 1
m['barney'] += 1

Now the reason "m['barney'] += 1" works in the former is becasue "+=" 
actually returns a value to which the name on the left gets re-assigned. 
"<<" does not work this way, so it can't be done as easily.

You might want to make a named method that thinks for you. The resulting 
  code is less terse but more clear (i.e. pythonic):

def meh_append(ameh, key, value):
   if not ameh.has_key(key):
     ameh[key] = [value]

def meh_addleaf(ameh, key, value={}):
   if value == {}:
     ameh[key] = {}
     ameh[key] = value

m = meh()

meh_addleaf(m['bob'], 'carol', None)
meh_append(m['ted'], 'alice', 14)
meh_append(m, 'fred', 1)
meh_append(m, 'fred', 2)

print m # {'bob': {'carol': None},
         #  'ted': {'alice': [14]}, 'fred': [1, 2]}

But now its getting very pythonic. And the only magic we need is the 
original __getattr__ modification, which we could find a way of 
eliminating if we tried.


More information about the Python-list mailing list