Dave Dave - 2 months ago 10
Python Question

Python: linking/binding variables together in a dictionary

first post, so play nice!

I have a fairly basic question about Python dictionaries. I would like to have some dict value that updates when another variable is changed (or at least recalculated when it is next called) - eg:

mass = 1.0
volume = 0.5
mydict = {'mass':mass,'volume':volume}
mydict['density'] = mydict['mass']/mydict['volume']


So in this case, mydict['density'] just returns 2.0. If I change mydict['mass'] = 2.0, the density will not be updated. Fine - I can kind of understand why - the density is defined by the values when they were passed to the declaration. So I thought maybe I could approach this with a lambda expression, eg (apologies for the horrid code!):

mydict['density_calc'] = lambda x,y: x/y
mydict['density'] = mydict['density_calc'](mydict['mass'],mydict['volume'])


But again, this only returns the original density, despite changing mydict['mass']. As a final attempt, I tried this:

def density(mass,volume): return mass/volume
mydict['density_calc'] = lambda x,y: density(x,y)
mydict['density'] = mydict['density_calc'](mydict['mass'],mydict['volume'])


Again, no dice. This seems like a really simple problem to solve, so apologies in advance, but if anyone could help me out, I'd be very appreciative!

Cheers,

Dave

Answer

Here's a quick hack on how to subclass dict to meet your specs, but probably not to meet Python's specs for a dictionary:

class MyDict(dict):
    def __getitem__(self, key):
        if key == 'density':
           return self['mass'] / self['volume']
        else:
            return dict.__getitem__(self,key)
    def keys(self):
        return ['density'] + dict.keys(self)

x = MyDict()
x['mass'] = 1.0
x['volume'] = 0.5

print x

print x.keys()

print x['density']

x['mass'] = 2.0

print x['density']

which prints

{'volume': 0.5, 'mass': 1.0}
['density', 'volume', 'mass']
2.0
4.0

But that doesn't account for dict.iterkeys(), among other things.