1

Following is my requirement which is to be implemented in python: I have a dictionary called context which will be updated from various parts of the program.

Now I have to create an obj called env which holds the dictionary context and environmental variables dictionary also.

env object should have all features of dictionary class along with it, it should be possible to the access the item of dictionary as attribute of the object.

For example,

context = {'install_path' : '/home/xyz','cwd' : '/home/xyz/Desktop'}

the

context dictionary will be updated from various parts of program.

Now I have to create env object which holds context dictionary and also environmental dictionary. And It should be possible to access the items of dictionary as attributes of env object.

For example:

print(env.install_path) # accessing item of context dictionary
print(env.os) #accessing environmental variable print(env)
print(env['install_path'])
print(env)

should produce output as:

 /home/xyz linux 
 /home/xyz
 {'install_path':'/home/xyz','cwd':'/home/xyz/Desktop'}
 all envrionmental variables

Later when the context dictionary is updated the env object should also be updated.

Please help how to achieve this.

user19911303
  • 449
  • 2
  • 9
  • 34
Vinay Surve
  • 85
  • 1
  • 6
  • It's possible, but why would you want to allow this? It just makes things more confusing - not easier... – Jon Clements Feb 27 '13 at 06:23
  • @JonClements: That is how the requirement is – Vinay Surve Feb 27 '13 at 06:24
  • 2
    Umm, so what happens if a variable is called `update` `pop` `get` `keys` `items` etc... ? – Jon Clements Feb 27 '13 at 06:24
  • @JonClements: All should work as expected with their common behaviour – Vinay Surve Feb 27 '13 at 06:27
  • @WesleyBaugh That's what I was thinking - was just trying to work out if there was something more to the question. But yeah - the OP should read that and see if it meets their requirement. – Jon Clements Feb 27 '13 at 06:27
  • @WesleyBaugh: It seems to work.. But, when will print(env) work?? – Vinay Surve Feb 27 '13 at 06:29
  • I just tested [this answer](http://stackoverflow.com/a/14620633/1988505) on that question, and it **correctly** handles the [problem example](http://stackoverflow.com/a/9288569/1988505) shown in another answer. – Wesley Baugh Feb 27 '13 at 06:31
  • I just tested with [answer](http://stackoverflow.com/questions/4984647/accessing-dict-keys-like-an-attribute-in-python/9288569#9288569) But its doesn't meet my requirements – Vinay Surve Feb 27 '13 at 06:38

3 Answers3

2

This is the simplest way to do something like that I've seen:

class AttrDict(dict):
    def __init__(self, *args, **kwargs):
        super(AttrDict, self).__init__(*args, **kwargs)
        self.__dict__ = self

if __name__ == '__main__':
    o = AttrDict(x=10)
    o.y = 20
    o['z'] = 30
    print o.x, o['y'], o.z

Output:

10 20 30
martineau
  • 119,623
  • 25
  • 170
  • 301
0

Create a subclass of dict.

Objects have methods that get called if an attribute is missing. You can override the default implementation of these methods to do dictionary get and set operations.

class AttributeDict(dict):
    def __getattr__(self, attr):
        return self[attr]
    def __setattr__(self, attr, value):
        self[attr] = value

Previous discussion here

If you need to create a new AttributeDict from an existing dictionary, you can use the following:

context = {'install_path' : '/home/xyz','cwd' : '/home/xyz/Desktop'}
new_dict = AttributeDict(context)
print new_dict.install_path

If you want a different object that just references an existing dictionary, use this

class ReferencedDict(object):
    def __init__(self, reference):
        self.ref = reference
    def __getattr__(self, value):
        return self.ref[value]

env = ReferencedDict(context)
print(env)
Community
  • 1
  • 1
matt
  • 1,895
  • 5
  • 19
  • 26
  • I tested this answer , but it doesn't cover all my requirements.. I have a dictionary which is already created and I have to create a object hold both the context dictionary and environmental dictionary.Also `print(env)` should also work – Vinay Surve Feb 27 '13 at 06:44
  • Which requirements does it specifically not cover? – matt Feb 27 '13 at 06:47
  • `print(env)` This should display the contents of `context` dictionary along with environmental dictionary – Vinay Surve Feb 27 '13 at 06:50
  • @vinaysurve: It's not a huge conceptual leap to create an object with two `AttributeDict`s, `env` and `context`. What's the problem? – Joel Cornett Feb 27 '13 at 07:47
  • @JoelCornett: All seems to work. But when I add some items in to `context` dictionary , that is not reflected in `env` object – Vinay Surve Feb 27 '13 at 08:24
  • I did like this: `class Env(dict): __getattr = dict.__getitem__` then created object of Env like : `context = {'name' : 'vinay'} env = Env(context)` Now its possible to access `env.name` but later if i update `context` as `context['path'] = '/home/vinay'` and if I try to access `path` as `env.path` I got keyerror as `env` object is not updated. How to slove this? – Vinay Surve Feb 27 '13 at 08:25
0

Something like this should do the trick:

class DictWithReference(dict):

    def __init__(self, *args, **kwargs):
        self._ref_other = kwargs.pop("ref", {})
        super(DictWithReference, self).__init__(*args, **kwargs)

    def __getattr__(self, attr):
        return self.__getitem__(attr)

    def __getitem__(self, key):
        try:
            return super(DictWithReference, self).__getitem__(attr)
        except KeyError:
            return self._ref_other[attr]

Usage:

>>> context = {'install_path' : '/home/xyz','cwd' : '/home/xyz/Desktop'}
>>> env = DictWithReference({'foo': 'bar'}, ref=context)
>>> env.foo
'bar'
>>> env['foo']
'bar'
>>> env.install_path
'/home/xyz'
>>> env['install_path']
'/home/xyz'
Joel Cornett
  • 24,192
  • 9
  • 66
  • 88