Python: Declaring Dynamic Attributes
The examples below are in Python 3.5, but otherwise this post is applicable to both Python 2.x and 3.x
It is a common solution in Python to override the __getattr__
magic method in classes, to implement dynamic attributes. Consider AttrDict
- it is a dictionary that allows attribute-like access to its stored key-value pairs:
class AttrDict(dict):
def __getattr__(self, item):
return self[item]
This simplified AttrDict
allows to read dictionary values from it like attributes, but it’s pretty simple to also allow to set key-value pairs. At any rate, here it is in action:
>>> attrd = AttrDict()
... attrd["key"] = "value"
... print(attrd.key)
value
Overriding __getattr__
(and __setattr__
) is very useful - from simple “gimmicks” like AttrDict
that makes your code more readable to essential building blocks of your application like remote procedure callers (RPCs). There is, however, something a little bit frustrating about dynamic attributes - you can’t see them before you use them!
Dynamic attributes have two usability problems when working in an interactive shell. The first is that they don’t appear when a user tries to examine the object’s API by calling the dir
method:
>>> dir(attrd) # I wonder how I can use attrd
['__class__', '__contains__', ... 'keys', 'values']
>>> # No dynamic attribute :(
The second problem is autocompletion - if we set normal_attribute
as an attribute the old fashioned way, we get autocompletion from most modern shell environments1:

But setting dynamic_attribute
by inserting it as a dictionary key-value pair does not provide us with autocompletion:

There is, however, an extra step you can take when implementing dynamic attributes which will make it a delight for your users and kill two birds with one stone - implement the __dir__
method. From the docs:
If the object has a method named
__dir__()
, this method will be called and must return the list of attributes. This allows objects that implement a custom__getattr__()
or__getattribute__()
function to customize the waydir()
reports their attributes.
Implementing __dir__
is straightforward: return a list of attribute names for the object:
class AttrDict(dict):
def __getattr__(self, item):
return self[item]
def __dir__(self):
return super().__dir__() + [str(k) for k in self.keys()]
This will make dir(attrd)
return dynamic attributes as well as the regular ones. The interesting thing about this is that shell environments often use __dir__
to suggest autocompletion options! so without any additional effort, we also get autocompletion2:

Follow me on Twitter and Facebook
Thanks to Ram Rachum for reading drafts of this.