bidict/docs/intro.rst

111 lines
3.1 KiB
ReStructuredText
Raw Normal View History

.. _intro:
2016-06-28 04:05:22 +00:00
Introduction
============
2016-06-28 04:05:22 +00:00
The :mod:`bidict` package provides a Pythonic
`bidirectional map <https://en.wikipedia.org/wiki/Bidirectional_map>`_
2016-06-28 04:05:22 +00:00
implementation
and related functionality to work with one-to-one mappings in Python.
bidict.bidict
-------------
:class:`bidict.bidict`
is the main bidirectional map data structure provided.
It implements the familiar API you're used to from dict::
>>> from bidict import bidict
>>> element_by_symbol = bidict(H='hydrogen')
>>> element_by_symbol
bidict({'H': 'hydrogen'})
>>> element_by_symbol['H']
'hydrogen'
But it also maintains the inverse bidict via the
:attr:`inv <bidict.BidirectionalMapping.inv>` attribute::
>>> element_by_symbol.inv
bidict({'hydrogen': 'H'})
2015-04-27 22:20:03 +00:00
>>> element_by_symbol.inv['hydrogen']
'H'
>>> element_by_symbol.inv.inv is element_by_symbol
True
Concise, efficient, Pythonic.
2016-06-28 04:05:22 +00:00
Why Can't I Just Use A dict?
----------------------------
2015-04-27 22:20:03 +00:00
A skeptic writes:
If I want a mapping *a* ↔︎ *b*,
2016-06-28 04:05:22 +00:00
I would just create a dict ``{a: b, b: a}``.
2015-04-27 22:20:03 +00:00
What is the advantage of bidict
over the simplicity of the dict approach?
Glad you asked.
For one, you don't have to manually update the mapping *b* → *a*
whenever the mapping *a* → *b* changes.
With the skeptic's method,
if *a* → *b* needs to change to *a* → *c*,
you have to write::
>>> d[a] = c # doctest: +SKIP
>>> d[c] = a # doctest: +SKIP
>>> del d[b] # doctest: +SKIP
With bidicit, you can instead just write::
>>> d[a] = c # doctest: +SKIP
2015-04-27 22:20:03 +00:00
and the rest is taken care of for you.
2015-04-27 22:20:03 +00:00
But even more important,
since the dict approach
inserts values as keys into the same one-directional map it inserts keys into,
it's not a bidirectional map so much as
the destructive merge of two one-directional maps into one.
2015-04-27 22:20:03 +00:00
In other words,
you lose information about which mappings are the forward mappings
and which are the inverse.
2016-06-28 04:05:22 +00:00
``d.keys()`` and ``d.values()`` would each give you
the same 2x-too-big jumble of keys and values
all mixed together,
2016-06-28 04:05:22 +00:00
and ``d.items()`` would likewise be
the 2x-too-big combination of forward and inverse mappings
all mixed together.
2015-04-27 22:20:03 +00:00
In short,
to model a bidirectional map,
you need two separate one-directional maps
2015-04-27 22:20:03 +00:00
that are kept in sync as the bidirectional map changes.
This is exactly what bidict does under the hood,
2016-06-28 04:05:22 +00:00
abstracting this into a clean and simple interface.
bidict also provides rich and powerful facilities
to help you handle the enforcement of the one-to-one constraint
(for example, when attempting to set a new key to an existing value)
exactly as you intend.
2015-04-27 22:20:03 +00:00
Additional Functionality
------------------------
2016-06-28 04:05:22 +00:00
Besides the standard :class:`bidict.bidict` class,
the :mod:`bidict` package provides other bidict variants,
as well as additional tools
for working with one-to-one relations:
- :class:`bidict.frozenbidict`
- :class:`bidict.loosebidict`
2015-12-25 19:13:02 +00:00
- :class:`bidict.orderedbidict`
- :class:`bidict.namedbidict`
- :class:`bidict.inverted`
2016-06-28 04:05:22 +00:00
- :class:`bidict.pairs`
2016-06-28 04:05:22 +00:00
These and other provided functionality are covered in later sections.
But first let's proceed to :ref:`basic-usage`.