I find it more convenient to access dict keys as obj.foo
instead of obj[\'foo\']
, so I wrote this snippet:
class AttributeDict(dict
No need to write your own as setattr() and getattr() already exist.
The advantage of class objects probably comes into play in class definition and inheritance.
This isn't a 'good' answer, but I thought this was nifty (it doesn't handle nested dicts in current form). Simply wrap your dict in a function:
def make_funcdict(d=None, **kwargs)
def funcdict(d=None, **kwargs):
if d is not None:
funcdict.__dict__.update(d)
funcdict.__dict__.update(kwargs)
return funcdict.__dict__
funcdict(d, **kwargs)
return funcdict
Now you have slightly different syntax. To acces the dict items as attributes do f.key
. To access the dict items (and other dict methods) in the usual manner do f()['key']
and we can conveniently update the dict by calling f with keyword arguments and/or a dictionary
d = {'name':'Henry', 'age':31}
d = make_funcdict(d)
>>> for key in d():
... print key
...
age
name
>>> print d.name
... Henry
>>> print d.age
... 31
>>> d({'Height':'5-11'}, Job='Carpenter')
... {'age': 31, 'name': 'Henry', 'Job': 'Carpenter', 'Height': '5-11'}
And there it is. I'll be happy if anyone suggests benefits and drawbacks of this method.
From This other SO question there's a great implementation example that simplifies your existing code. How about:
class AttributeDict(dict):
__slots__ = ()
__getattr__ = dict.__getitem__
__setattr__ = dict.__setitem__
Much more concise and doesn't leave any room for extra cruft getting into your __getattr__
and __setattr__
functions in the future.
Let me post another implementation, which builds upon the answer of Kinvais, but integrates ideas from the AttributeDict proposed in http://databio.org/posts/python_AttributeDict.html.
The advantage of this version is that it also works for nested dictionaries:
class AttrDict(dict):
"""
A class to convert a nested Dictionary into an object with key-values
that are accessible using attribute notation (AttrDict.attribute) instead of
key notation (Dict["key"]). This class recursively sets Dicts to objects,
allowing you to recurse down nested dicts (like: AttrDict.attr.attr)
"""
# Inspired by:
# http://stackoverflow.com/a/14620633/1551810
# http://databio.org/posts/python_AttributeDict.html
def __init__(self, iterable, **kwargs):
super(AttrDict, self).__init__(iterable, **kwargs)
for key, value in iterable.items():
if isinstance(value, dict):
self.__dict__[key] = AttrDict(value)
else:
self.__dict__[key] = value
The best way to do this is:
class AttrDict(dict):
def __init__(self, *args, **kwargs):
super(AttrDict, self).__init__(*args, **kwargs)
self.__dict__ = self
Some pros:
.keys()
work just fine. Unless - of course - you assign some value to them, see below)AttributeError
instead of KeyError
Cons:
.keys()
will not work just fine if they get overwritten by incoming dataAttrDict
instance actually stores 2 dictionaries, one inherited and another one in __dict__
E1123(unexpected-keyword-arg)
and E1103(maybe-no-member)
__dict__
.__dict__
would need to be "just a plain dict", so we can assign any subclass of dict()
to the internal dictionary.AttrDict()
instance we are instantiating (as we are in __init__
).super()
's __init__()
method we made sure that it (already) behaves exactly like a dictionary, since that function calls all the dictionary instantiation code.As noted in the "cons" list, this combines the namespace of stored keys (which may come from arbitrary and/or untrusted data!) with the namespace of builtin dict method attributes. For example:
d = AttrDict()
d.update({'items':["jacket", "necktie", "trousers"]})
for k, v in d.items(): # TypeError: 'list' object is not callable
print "Never reached!"
Since this question was asked almost ten years ago, quite a bit has changed in Python itself since then.
While this approach is still valid for some cases, e.g. legacy projects stuck to older versions of Python and cases where you really need to handle dictionaries with very dynamic string keys - I think that in general the dataclasses introduced in Python 3.7 are the obvious/correct solution to vast majority of the use cases of AttrDict.
What if you wanted a key which was a method, such as __eq__
or __getattr__
?
And you wouldn't be able to have an entry that didn't start with a letter, so using 0343853
as a key is out.
And what if you didn't want to use a string?