🧊 A memory-efficient, fully immutable dictionary for Python, powered by Rust.
Project description
frozndict is a production-grade, fully immutable Python dictionary powered by Rust and PyO3. It is a drop-in companion to frozenset for dictionaries - hashable, thread-safe, and built for performance.
🚀 The Fastest, Most Efficient Immutable Dictionary
frozndict pushes immutable mappings to the absolute mathematical limits. While every other library wraps a standard Python hash-table, frozndict is engineered ground-up in Rust as a hash-sorted flat slice - a single contiguous heap block, binary-searched by native isize keys with zero FFI crossings during the search phase.
🏆 Fastest Iteration in Class Keys, values, and items lists are pre-built once at construction time as cached Python objects. Every subsequent keys() / values() / items() / iteration call is an O(1) reference clone - no per-call allocation at all.
Deterministic O(1) Pre-Computed Hashing The dict-level hash is XOR-combined over all (k, v) pairs exactly once at construction and stored as a native isize. Every hash(d) call costs only a Python integer return - ~0.3 µs regardless of size. Regular dict cannot be hashed at all.
🏆 Smallest Memory Footprint in Class Entries sit in a single flat Box<[(isize, K, V)]> allocation - no bucket arrays, no load-factor slack, no pointer tables. Python sees exactly 64 bytes regardless of element count vs 6,584 bytes for frozendict at n=200.
Infallible Rust-Level Immutability Mutation is blocked inside the Rust binary - not via Python descriptor tricks. There is no monkey-patchable __setattr__ escape path.
Run the full benchmark suite locally:
$ python3 -m venv .venv $ source .venv/bin/activate $ pip install maturin $ maturin develop --features python $ pip install frozendict $ python3 benchmarks/benchmark.py
Metric (200 Elements) |
frozndict (Rust) |
frozendict (C) |
dict |
|---|---|---|---|
Memory Size SMALLEST 🏆 |
64 B |
6,584 B |
6,576 B |
Lookup (Worst-Case) |
0.756 µs |
0.057 µs |
0.035 µs |
Iteration (keys) FASTEST 🏆 |
0.877 µs |
1.895 µs |
1.977 µs |
Cached Hashing |
0.280 µs |
0.199 µs |
not hashable |
🛠️ Requirements
Python 3.12+
Rust 1.89+ (only when building from source)
Maturin 1.14+ (only when building from source)
🚨 Installation
With pip:
python3 -m pip install frozndict
Build from source for development:
git clone https://github.com/wiseaidev/frozndict.git cd frozndict python3 -m venv .venv source .venv/bin/activate pip install maturin maturin develop --features python
🚸 Usage
>>> from frozndict import frozendict
# Empty immutable dictionary.
>>> frozendict({})
frozendict({})
# From a plain dict.
>>> frozen_dict = frozendict({"Greetings": "Hello World!"})
>>> frozen_dict["Greetings"]
'Hello World!'
# From keyword arguments.
>>> frozendict(a=1, b=2)
frozendict({'a': 1, 'b': 2})
# Pretty-printed representation (all values must be hashable).
>>> print(frozendict(x=3, y=4, z="nested-str", c=1).pretty_repr())
frozendict({
'c': 1,
'y': 4,
'z': 'nested-str',
'x': 3,
})
# Values must be hashable - frozndict hashes every (key, value) pair at construction.
# Use frozendict/frozenset for nested immutable structures:
>>> frozendict(x=1, tags=frozenset(["a", "b"]))
frozendict({'x': 1, 'tags': frozenset({'b', 'a'})})
# fromkeys constructor.
>>> frozendict.fromkeys(["x", "y"], "5")
frozendict({'x': '5', 'y': '5'})
# Fully hashable - use as dictionary keys or set members.
>>> set([frozendict(a=1, b=2), frozendict(a=5), frozendict(b=2, a=1)])
{frozendict({'a': 1, 'b': 2}), frozendict({'a': 5})}
# Hash is order-independent and O(1).
>>> hash(frozendict(a=1, b=2)) == hash(frozendict(b=2, a=1))
True
# Mutation raises TypeError - enforced at the Rust binary level.
>>> frozen_dict["x"] = 1
TypeError: 'frozendict' object does not support mutation
🎉 Credits
Built with: python · PyO3 · maturin · pytest · black · isort · flake8 · precommit
👋 Contribute
Please refer to the Guideline for contribution instructions.
📝 License
Released under the MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file frozndict-2.0.0-cp312-cp312-manylinux_2_34_x86_64.whl.
File metadata
- Download URL: frozndict-2.0.0-cp312-cp312-manylinux_2_34_x86_64.whl
- Upload date:
- Size: 225.4 kB
- Tags: CPython 3.12, manylinux: glibc 2.34+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a205f3045918441b70baa0be738b49defca80e445b0ca73b35e4e94f915e3c4
|
|
| MD5 |
48989e51f4451309cd3f92690d372361
|
|
| BLAKE2b-256 |
1f9f17cf0479c6d51fcc05d80bc771f4eadf4911a702ffac6dfebee65bbb76c3
|