Skip to main content
Latest PyPI version Number of PyPI downloads Test odict

odict

Dictionary in which the insertion order of items is preserved (using an internal double linked list). In this implementation replacing an existing item keeps it at its original position.

Internal representation: values of the dict.

[pred_key, val, succ_key]

The sequence of elements uses as a double linked list. The links are dict keys. self.lh and self.lt are the keys of first and last element inserted in the odict.

Motivation

When this package was created, collections.OrderedDict not existed yet.

Another problem is that dict cannot always be inherited from in conjunction with other base classes. This may result in instance layout conflicts or other errors. So odict is written in a way that let you alter the dictionary base implementation.

Usage

Import and create ordered dictionary.

from odict import odict
od = odict()

Custom odict

It is possible to use _odict base class to implement an ordered dict not inheriting from dict type. This is useful i.e. when persisting to ZODB.

Inheriting from dict and Persistent at the same time fails. Also, using a regular list for the internal double linked list representation causes problems, so we define a custom class for it as well.

from persistent.dict import PersistentDict
from persistent.list import PersistentList

class podict(_odict, PersistentDict):

    def _dict_impl(self):
        return PersistentDict

    def _list_factory(self):
        return PersistentList

Python < 3.7

In Python < 3.7 casting to dict will fail. The reason for this can be found here. The __init__ function of dict checks whether arg is subclass of dict, and ignores overwritten __getitem__ & co if so. This was fixed and later reverted due to behavioural problems with pickle:

>>> dict(odict([(1, 1)]))
{1: [nil, 1, nil]}

Use one of the following ways for type conversion.

>>> dict(odict([(1, 1)]).items())
{1: 1}

>>> odict([(1, 1)]).as_dict()
{1: 1}

Misc

In a C reimplementation of this data structure, things could be simplified (and speed up) a lot if given a value you can at the same time find its key. With that, you can use normal C pointers.

Python Versions

  • Python 2.7, 3.7+

  • Probably works with other/older versions

Contributors

  • bearophile (Original Author)

  • Robert Niederreiter (Author)

  • Georg Bernhard

  • Florian Friesdorf

  • Jens Klein

under the Python Software Foundation License.

Changes

2.0.0 (2026-02-03)

  • Improve __len__ function to use underlying dict implementation directly. [rnix]

  • Deprecate _odict. user _base_odict instead. [rnix]

  • Rename _dict_impl to _dict_cls and _list_factory to _list_cls. [rnix]

  • Refactor package layout to use pyproject.toml. [rnix]

  • Drop Python 2 support. [rnix]

1.9.0 (2022-05-15)

  • Add movebefore, moveafter, movefirst and movelast functions to odict. [rnix]

  • Use first_key and last_key in insertfirst and insertlast instead of reading all keys. [rnix]

1.8.1 (2022-03-17)

  • Do not run test suites for Python 2.6 and Python < 3.7 any more. No changes to the implementation have been made. [rnix]

  • Package housekeeping. [rnix]

1.8.0

  • Add next_key and prev_key functions. [rnix]

  • Add first_key and last_key properties. [rnix]

  • Add _list_factory on _odict base class. Can be used to alter the list implementation used for internal value triples. [rnix]

1.7.0

  • Add swap, insertbefore, insertafter, insertfirst and insertlast functions to odict. [rnix]

1.6.2

  • Use class name instead of ‘odict()’ in __repr__. [rnix]

1.6.1

  • pypi masness. [rnix]

1.6.0

  • Compatible with Python 3 and pypy. [rnix]

1.5.2

  • Fix permission problem in 1.5.1 release, some files were only rw by user. [jensens, 2016-11-25]

1.5.1

  • Implement __copy__ and __deepcopy__ in order to work with Python 2.7. [rnix, 2012-10-15]

  • Use try/except instead of in in __contains__. [rnix, 2012-10-15]

1.5.0

  • Implement alter_key. [rnix, 2012-05-18]

1.4.4

  • Remove unused error variable. [rnix, 2011-11-28]

  • Add note on why to check with == and != against _nil. [rnix, 2011-11-28]

1.4.3

  • Get rid of annoying warning about “global” usage in bench.py. [jensens, 2011-09-20]

1.4.2

  • More copy testing. [rnix, 2010-12-18]

  • Add has_key to odict. [rnix, 2010-12-18]

1.4.1

  • Fix release, README.rst was missing, added MANIFEST.in file to include it. [jensens, 2010-11-29]

1.4.0

  • Full test coverage. [chaoflow, rnix, 2010-08-17]

  • Code cleanup and optimizing. [chaoflow, rnix, 2010-08-17]

1.3.2

  • Access dict API providing class via function _dict_impl() and provide odict logic as abstract base class _odict. [rnix, 2010-07-08]

1.3.1

  • Add test for bool evaluation. [rnix, 2010-04-21]

1.3.0

  • Fix access to odict.lt and odict.lh properties. Now it’s possible to overwrite __setattr__ and __getattr__ on odict subclass without hassle. [rnix, 2010-04-06]

  • Add sort function to odict. [rnix, 2010-03-03]

1.2.6

  • Make odict serialize and deserialize properly. [gogo, 2010-01-12]

1.2.5

  • Add as_dict function. Supports type conto ordinary dict. [rnix, 2009-12-19]

  • Add benchmark script. [rnix, 2009-12-19]

1.2.4

  • Do not check for key in self on __delitem__, KeyError is raised properly anyway. Huge Speedup! [rnix, jensens, 2009-12-18]

1.2.3

  • Move tests to seperate file and make egg testable with python setup.py test. [rnix, 2009-12-07]

  • improve lt and lh properties to make odict work with copy.deepcopy. [rnix, 2009-12-07]

1.2.2

  • Use try/except instead of __iter__ in __setitem__ to determine if value was already set. [rnix, 2009-07-17]

1.2.1

  • Add missing __len__ and __contains__ functions. [rnix, 2009-03-17]

1.2.0

  • Eggified [rnix, 2009-03-17]

< 1.2

License

PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2

1. This LICENSE AGREEMENT is between the Python Software Foundation (“PSF”), and the Individual or Organization (“Licensee”) accessing and otherwise using this software (“Python”) in source or binary form and its associated documentation.

2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python alone or in any derivative version, provided, however, that PSF’s License Agreement and PSF’s notice of copyright, i.e., “Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Python Software Foundation; All Rights Reserved” are retained in Python alone or in any derivative version prepared by Licensee.

3. In the event Licensee prepares a derivative work that is based on or incorporates Python or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python.

4. PSF is making Python available to Licensee on an “AS IS” basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.

5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.

6. This License Agreement will automatically terminate upon a material breach of its terms and conditions.

7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party.

8. By copying, installing or otherwise using Python, Licensee agrees to be bound by the terms and conditions of this License Agreement.

Metadata

Release files for odict 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for odict 2.0.0
File Size Uploaded Provenance
odict-2.0.0.tar.gz 15.3 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for odict 2.0.0
File Interpreter ABI Platform
odict-2.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 26.3 kB

Release files / odict-2.0.0.tar.gz

Download URL odict-2.0.0.tar.gz
Size 15.3 kB
Tags Source
SHA-256 checksum
How to use checksums
26fa21a9cc07d1b7231aab2fbcf63dd8f0ae14172d39bc355f070cd0e801072a
BLAKE2b-256 checksum
How to use checksums
65f94f37b0c639673b61e408f7e69b80f2faa3fea2941fa5ebb93677c42833c0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Release files / odict-2.0.0-py3-none-any.whl

Download URL odict-2.0.0-py3-none-any.whl
Size 11.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
892d0e4ceef679c2f04899645bc36f49904e87ec05765183cb56a94c133a5aab
BLAKE2b-256 checksum
How to use checksums
05823489ac834f0de9c489dacc00f98a209f1604c29f5ef3d7a3d07a1a8590a1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Security for odict 2.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page