benjsec
benjsec

Reputation: 23

Python self referential dictionary with class

I'm trying to make a list of parameters as a dictionary within a class. Because of the nature of the data some of the parameters are derived from others, but used sufficiently often that I would prefer to keep their derivation within the parameters dictionary. I've managed to put together a self-referential dictionary which works fine when I can name the dictionary directly, but because it's part of a class and may be implemented in lots of different files I'm having difficulty in getting it to be able to name itself.

class foo:
    class ParamDict(dict):
        def __getitem__(self, key):
            val = dict.__getitem__(self, key)
            return callable(val) and val() or val

    params = ParamDict({
        'a': 5,
        'b': lambda: 2**self['a']
        })

if __name__ == '__main__':
    X = foo()
    Y = foo()
    Y.params['a'] = 3

    print X.params['a'], X.params['b']
    print Y.params['a'], Y.params['b']

Because I don't know where the lambda function will be called from I don't know how to give it a reference to the dictionary, it doesn't seem to pick up the 'self' from the getitem definition, unfortunately. Any suggestions?

Upvotes: 2

Views: 2538

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1124518

self doesn't just magically appear; Python functions are wrapped in methods when accessed via an instance (through invoking the function as a descriptor), and self is then passed in to the function as a first argument.

For your lambdas, you'll need to pass self in explicitly:

class ParamDict(dict):
    def __getitem__(self, key):
        val = dict.__getitem__(self, key)
        return callable(val) and val(self) or val

params = ParamDict({
    'a': 5,
    'b': lambda self: 2**self['a']
    })

Upvotes: 5

Related Questions