File: subclassing.rst

package info (click to toggle)
python-boost-histogram 1.7.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,236 kB
  • sloc: python: 7,940; cpp: 3,243; makefile: 22; sh: 1
file content (47 lines) | stat: -rw-r--r-- 2,808 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
.. _usage-subclassing:


Subclassing (advanced)
======================

Subclassing boost-histogram components is supported, but requires a little extra care to ensure the subclasses do not return un-wrapped boost-histogram components when a subclassed version is available. The issue is that various actions make the C++ -> Python transition over again, such as using ``.project()``. For example, let's say you have a ``MyHistogram`` and a ``MyRegular``. If you use ``project(0)``, that needs to also return a ``MyRegular``, but it is reconverting the return value from C++ to Python, so it has to somehow know that ``MyRegular`` is the right axis subclass to select from for ``MyHistogram``. This is accomplished with families.

When you subclass, you will need to add a family. Any object can be used - the module for your library is a good choice if you only have one "family" of histograms. Boost-histogram uses ``boost_histogram``, Hist uses ``hist``. You can use anything you want, though; a custom tag object like ``MY_FAMILY = object()`` works well too. It just has to support ``is``, and be the exact same object on all your subclasses.

.. code-block:: python3

    import boost_histogram as bh
    import my_package


    class Histogram(bh.Histogram, family=my_package): ...


    class Regular(bh.axis.Regular, family=my_package): ...

If you only override ``Histogram``, you can leave off the ``family=`` argument, or set it to ``None``. It will generate a private ``object()`` in this case. You must add an explicit family to ``Histogram`` if you subclass any further components.

If you use Mixins, special care needs to be taken if you need a left-acting
Mixin, since class keywords are handled via ``super()`` left to right. This is
a Mixin that will work on either side:

.. code-block:: python3

    class AxisMixin:
        def __init_subclass__(cls, **kwargs):
            super().__init_subclass__(**kwargs)  # type: ignore

Mixins are recommended if you want to provide functionality to a collection of
different subclasses, like ``Axis``.

There are customization hooks provided for subclasses as well.
``self._generate_axes_()`` is called to produce an ``AxesTuple``, so you can
override that if you customize ``AxesTuple``.

``_import_bh_`` and ``_export_bh_`` are called when converting an object between histogram
libraries. ``cls._export_bh_(self)`` is called from the outgoing class (being
converted from), and ``self._import_bh_()`` is called afterward on the incoming
class (being converted to). So if ``h1`` is an instance of ``H1``, and ``H2``
is the new class, then ``H2(h1)`` calls ``H1._export_bh_(h2)`` and then
``h2._import_bh_()`` before returning ``h2``. The internal repr building for axes is
a list produced by ``_repr_args_`` representing each item in the repr.