Skip to main content

A dict with attribute-style access

Project description

AttrDict is a 2.6, 2.7, 3-compatible dictionary that allows its elements to be accessed both as keys and as attributes:

> from attrdict import AttrDict
> a = AttrDict({'foo': 'bar'})
> a['foo']

With this, you can easily create convenient, heirarchical settings objects.

with open('settings.yaml', 'r') as fileobj:
    settings = AttrDict(yaml.safe_load(fileobj))

cursor = connect(**settings.db.credentials).cursor()

cursor.execute("SELECT column FROM table");


AttrDict is in PyPI, so it can be installed directly using:

$ pip install attrdict

Or from Github:

$ git clone
$ cd AttrDict
$ python install


Documentation is available at



An empty AttrDict can be created with:

a = AttrDict()

Or, you can pass an existing dict (or other type of Mapping object):

a = AttrDict({'foo': 'bar'})

NOTE: Unlike dict, AttrDict will not clone on creation. AttrDict’s internal dictionary will be the same instance as the dict passed in.


AttrDict can be used exactly like a normal dict:

> a = AttrDict()
> a['foo'] = 'bar'
> a['foo']
> '{foo}'.format(**a)
> del a['foo']
> a.get('foo', 'default')

AttrDict can also have it’s keys manipulated as attributes to the object:

> a = AttrDict()
> = 'bar'
> del

Both methods operate on the same underlying object, so operations are interchangeable. The only difference between the two methods is that where dict-style access would return a dict, attribute-style access will return an AttrDict. This allows recursive attribute-style access:

> a = AttrDict({'foo': {'bar': 'baz'}})
> a['foo'].bar
AttributeError: 'dict' object has no attribute 'bar'

There are some valid keys that cannot be accessed as attributes. To be accessed as an attribute, a key must:

  • be a string
  • start with an alphabetic character
  • be comprised solely of alphanumeric characters and underscores
  • not map to an existing attribute name (e.g., get, items)

To access these attributes while retaining an AttrDict wrapper (or to dynamically access any key as an attribute):

> a = AttrDict({'_foo': {'bar': 'baz'}})
> a('_foo').bar


AttrDicts can be merged with eachother or other dict objects using the + operator. For conflicting keys, the right dict’s value will be preferred, but in the case of two dictionary values, they will be recursively merged:

> a = {'foo': 'bar', 'alpha': {'beta': 'a', 'a': 'a'}}
> b = {'lorem': 'ipsum', 'alpha': {'bravo': 'b', 'a': 'b'}}
> AttrDict(a) + b
{'foo': 'bar', 'lorem': 'ipsum', 'alpha': {'beta': 'a', 'bravo': 'b', 'a': 'b'}}

NOTE: AttrDict’s add is not associative, a + b != b + a:

> a = {'foo': 'bar', 'alpha': {'beta': 'b', 'a': 0}}
> b = {'lorem': 'ipsum', 'alpha': {'bravo': 'b', 'a': 1}}
> b + AttrDict(a)
{'foo': 'bar', 'lorem': 'ipsum', 'alpha': {'beta': 'a', 'bravo': 'b', 'a': }}


By default, items in non-string Sequences (e.g. lists, tuples) will be converted to AttrDicts:

> adict = AttrDict({'list': [{'value': 1}, 'value': 2]})
> for element in adict.list:
>     element.value

This will not occur if you access the AttrDict as a dictionary:

> adict = AttrDict({'list': [{'value': 1}, 'value': 2]})
> for element in adict['list']:
>     isinstance(element, AttrDict)

To disable this behavior globally, pass the attribute recursive=False to the constructor:

> adict = AttrDict({'list': [{'value': 1}, 'value': 2]}, recursive=False)
> for element in adict['list']:
>     isinstance(element, AttrDict)

When merging an AttrDict with another mapping, this behavior will be disabled if at least one of the merged items is an AttrDict that has set recursive to False.


A common usage for AttrDict is to use it in combination with settings files to create hierarchical settings:

from attrdict import AttrDict
import yaml

def load(*filenames):
    Returns a settings dict built from a list of settings files.

    filenames: The names of any number of settings files.
    settings = AttrDict()

    for filename in filenames:
        with open(filename, 'r') as fileobj:
            settings += yaml.safe_load(fileobj)

    return settings

By accepting multiple files, settings can allow for default settings and provide overrides, e.g.:

# config.yaml =
# emergency:
#   email:
#   message: Something went wrong
# user.yaml =
# emergency:
#   email:
settings = load('config.yaml', 'user.yaml')

assert == ''
assert settings.message == 'Something went wrong'


AttrDict is released under a MIT license.

Project details

Release history Release notifications

History Node


History Node


History Node


History Node


History Node


History Node


History Node


This version
History Node


History Node


History Node


History Node


History Node


History Node


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Filename, size & hash SHA256 hash help File type Python version Upload date
attrdict-0.3.1.macosx-10.9-x86_64.exe (75.0 kB) Copy SHA256 hash SHA256 Windows Installer any Jun 3, 2014
attrdict-0.3.1.tar.gz (6.2 kB) Copy SHA256 hash SHA256 Source None Jun 3, 2014

Supported by

Elastic Elastic Search Pingdom Pingdom Monitoring Google Google BigQuery Sentry Sentry Error logging CloudAMQP CloudAMQP RabbitMQ AWS AWS Cloud computing Fastly Fastly CDN DigiCert DigiCert EV certificate StatusPage StatusPage Status page