bidict/docs/intro.doctest.rst

109 lines
2.9 KiB
ReStructuredText
Raw Normal View History

.. _intro:
Intro
=====
The :mod:`bidict` package provides a
`bidirectional map <https://en.wikipedia.org/wiki/Bidirectional_map>`_
data structure
and related functionality to work with one-to-one mappings in Python,
Pythonically.
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.
Why Can't I Just Use dict?
--------------------------
2015-04-27 22:20:03 +00:00
A skeptic writes:
If I want a mapping *a* ↔︎ *b*,
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.
2015-12-25 19:13:02 +00:00
*d.keys()* and *d.values()* would each give you
the same 2x-too-big jumble of keys and values
all mixed together,
2015-12-25 19:13:02 +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,
abstracting this into a clean and simple interface,
while providing complementary functionality to boot.
2015-04-27 22:20:03 +00:00
Additional Functionality
------------------------
Besides :class:`bidict.bidict`,
the :mod:`bidict` package provides 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.frozenorderedbidict`
- :class:`bidict.looseorderedbidict`
- :class:`bidict.namedbidict`
- :class:`bidict.inverted`
These will be covered in later sections.
But first let's proceed to :ref:`basic-usage`.