9

Here's the pattern I'm thinking of using:

class Dicty(dict): 
    def __init__(self): 
         self.__dict__ = self 

d = Dicty()
d.foo = 'bar' 
print d['foo']
>>> bar 
d['foo'] = 'baz'
print d.foo
>>> 'baz'

Generally, I prefer the semantics of object attribute access over dict get/set access, but there are some circumstances where dict-like access is required (for example, d['foo-bar'] = 'baz') and I'd prefer not to have special getter setter methods for these cases, so thus, the dual behavior of dict & object at the same time with shared attributes.

Are there any gotchas with the above pattern?

skaffman
  • 398,947
  • 96
  • 818
  • 769
slacy
  • 11,397
  • 8
  • 56
  • 61
  • 1
    See: http://stackoverflow.com/questions/3031219/python-recursively-access-dict-via-attributes-as-well-as-index-access – Josh Lee Feb 16 '11 at 19:19
  • 1
    `isinstance(dict, object)`. You don't need to inherit from `object`. And the implementation is more than hacky. Also: possible duplicate of [Accessing dict keys like an attribute in Python?](http://stackoverflow.com/questions/4984647/accessing-dict-keys-like-an-attribute-in-python) –  Feb 16 '11 at 19:21
  • 1
    Objects created in this manner can be pickled without problem but objects created in the style suggested by the accepted answer cannot. – Gearoid Murphy Oct 20 '12 at 15:22

3 Answers3

10

Here's a less "hacky" way to achieve the same effect:

class Dicty(dict):
    def __getattr__(self, key):
        return self[key]

    def __setattr__(self, key, value):
        self[key] = value

I think that your way may work fine as well, but setting the __dict__ attribute like that seems a bit iffy style-wise, and is bound to raise some questions if anyone else ends up reading your code.

shang
  • 24,642
  • 3
  • 58
  • 86
3

Don't set self.__dict__. Call __init__(self, *args, **kwargs) on the superclass. Also, dict inherits from object so you don't need to specify it.

nmichaels
  • 49,466
  • 12
  • 107
  • 135
2

A couple of things. One is if you try and use a dictionary method, such as keys, you won't be able to get it now. There were some other issues I ran into, such as being pickle-able and copy-able.

But I have implemented something that does this without those problems. You can see it here, it's the AttrDict class in the dictlib.py module. That module also contains a class that can wrap another mapping style object, in cases where it can't be subclassed.

Keith
  • 42,110
  • 11
  • 57
  • 76