Fundamentals 10 min read

Introduction to Python Libraries: attrs, bidict, Box, dataclasses, and DottedDict

This article introduces five Python libraries—attrs, bidict, Box, dataclasses, and DottedDict—explaining their installation, core features, and practical code examples for simplifying data class creation, bidirectional mapping, nested data access, and configuration management.

Test Development Learning Exchange
Test Development Learning Exchange
Test Development Learning Exchange
Introduction to Python Libraries: attrs, bidict, Box, dataclasses, and DottedDict

1. attrs

attrs is a library that simplifies Python class definitions by automatically generating __init__, __repr__, __eq__, and other special methods.

Installation:

pip install attrs

Example – basic usage:

import attr
@attr.s
class Person:
    name = attr.ib()
    age = attr.ib()

p = Person(name="Alice", age=30)
print(p)  # Output: Person(name='Alice', age=30)

Example – default values:

@attr.s
class Person:
    name = attr.ib(default="Unknown")
    age = attr.ib(default=0)

p = Person(age=30)
print(p)  # Output: Person(name='Unknown', age=30)

Example – validator:

def positive_number(instance, attribute, value):
    if value < 0:
        raise ValueError("Age must be a positive number")

@attr.s
class Person:
    name = attr.ib()
    age = attr.ib(validator=positive_number)

try:
    p = Person(name="Alice", age=-1)
except ValueError as e:
    print(e)  # Output: Age must be a positive number

Example – converter:

@attr.s
class Person:
    name = attr.ib(converter=str)
    age = attr.ib(converter=int)

p = Person(name=123, age="30")
print(p)  # Output: Person(name='123', age=30)

Example – frozen instance:

@attr.s(frozen=True)
class Person:
    name = attr.ib()
    age = attr.ib()

p = Person(name="Alice", age=30)
try:
    p.age = 31
except attr.exceptions.FrozenInstanceError as e:
    print(e)  # Output: can't set attributes of frozen Person

Use case: Quickly define data classes for configuration objects, DTOs, etc.

2. bidict

bidict provides a bidirectional mapping where keys can be accessed as values and vice versa.

Installation:

pip install bidict

Example – basic usage:

from bidict import bidict
b = bidict({"a": 1, "b": 2})
print(b["a"])      # Output: 1
print(b.inv[1])    # Output: 'a'

Example – add new item:

b = bidict({"a": 1, "b": 2})
b["c"] = 3
print(b)  # Output: bidict({'a': 1, 'b': 2, 'c': 3})

Example – delete item:

b = bidict({"a": 1, "b": 2})
del b["a"]
print(b)  # Output: bidict({'b': 2})

Example – existence check:

b = bidict({"a": 1, "b": 2})
print("a" in b)      # Output: True
print(1 in b.inv)    # Output: True

Example – update multiple items:

b = bidict({"a": 1, "b": 2})
b.update({"c": 3, "d": 4})
print(b)  # Output: bidict({'a': 1, 'b': 2, 'c': 3, 'd': 4})

Use case: Useful for bidirectional look‑ups in NLP, database reverse mapping, etc.

3. Box

Box is a Python dictionary with advanced dot‑notation access, making nested data handling more convenient.

Installation:

pip install python-box

Example – basic usage:

from box import Box

data = {
    "person": {
        "name": "Alice",
        "age": 30,
        "address": {
            "street": "123 Main St",
            "city": "Anytown"
        }
    }
}
box_data = Box(data)
print(box_data.person.name)  # Output: Alice

Modify nested data:

box_data.person.age = 31
print(box_data)  # Shows updated age

Add new field:

box_data.person.email = "[email protected]"
print(box_data)  # Shows email added

Load data from a JSON file:

import json
with open('data.json') as f:
    data = json.load(f)
box_data = Box(data)
print(box_data.person.name)  # Output: Alice

Convert back to a plain dict:

dict_data = box_data.to_dict()
print(dict_data)  # Output: standard dictionary

Use case: Ideal for configuration management and JSON data manipulation.

4. dataclasses

dataclasses is part of the Python standard library that simplifies the creation of data classes by auto‑generating __init__, __repr__, __eq__, and more.

Example – basic usage:

from dataclasses import dataclass

@dataclass
class Person:
    name: str
    age: int

p = Person(name="Alice", age=30)
print(p)  # Output: Person(name='Alice', age=30)

Example – default values:

@dataclass
class Person:
    name: str = "Unknown"
    age: int = 0

p = Person(age=30)
print(p)  # Output: Person(name='Unknown', age=30)

Example – object comparison:

p1 = Person(name="Alice", age=30)
p2 = Person(name="Alice", age=30)
print(p1 == p2)  # Output: True

Example – immutable (frozen) dataclass:

@dataclass(frozen=True)
class Person:
    name: str
    age: int

p = Person(name="Alice", age=30)
try:
    p.age = 31
except FrozenInstanceError as e:
    print(e)  # Output: cannot assign to field 'age'

Example – inheritance:

@dataclass
class Employee(Person):
    employee_id: int

e = Employee(name="Bob", age=35, employee_id=123)
print(e)  # Output: Employee(name='Bob', age=35, employee_id=123)

Use case: Perfect for simple DTOs, configuration objects, and any scenario needing concise data containers.

5. DottedDict

DottedDict offers lightweight dot‑path access to nested dictionaries and lists, similar to Box.

Installation:

pip install dotted-dict

Example – basic usage:

from dotted_dict import DottedDict

data = {
    "person": {
        "name": "Alice",
        "age": 30,
        "address": {
            "street": "123 Main St",
            "city": "Anytown"
        }
    }
}

dotted_data = DottedDict(data)
print(dotted_data.get("person.name"))  # Output: Alice

Modify nested data:

dotted_data.set("person.age", 31)
print(dotted_data.to_dict())  # Shows updated age

Add new field:

dotted_data.set("person.email", "[email protected]")
print(dotted_data.to_dict())  # Shows email added

Load from JSON file:

import json
with open('data.json') as f:
    data = json.load(f)

dotted_data = DottedDict(data)
print(dotted_data.get("person.name"))  # Output: Alice

Convert back to dict:

dict_data = dotted_data.to_dict()
print(dict_data)  # Output: standard dictionary

Use case: Suitable for frequent nested dict/list manipulation in configuration management and JSON processing.

Pythoncode examplesdata-structuresattrsbidictboxdataclassesdotted-dict
Test Development Learning Exchange
Written by

Test Development Learning Exchange

Test Development Learning Exchange

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.