Repository: scipy/scipy
File: scipy/interpolate/_bary_rational.py (Python)

Code before:
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import warnings
import operator
from types import GenericAlias

import numpy as np
import scipy


__all__ = ["AAA", "FloaterHormannInterpolator"]


class _BarycentricRational:
    """Base class for barycentric representation of a rational function."""

    # generic type compatibility with scipy-stubs
    __class_getitem__ = classmethod(GenericAlias)

    _axis = 0
    def __init__(self, x, y, **kwargs):
        # input validation
        z = np.asarray(x)
        f = np.asarray(y)

        self._input_validation(z, f, **kwargs)

        f = np.moveaxis(f, self._axis, 0)

        # Remove infinite or NaN function values and repeated entries
        to_keep = np.logical_and.reduce(
            ((np.isfinite(f)) & (~np.isnan(f))).reshape(f.shape[0], -1),
            axis=-1
        )
        f = f[to_keep, ...]
        z = z[to_keep]
        z, uni = np.unique(z, return_index=True)
        f = f[uni, ...]

        self._shape = f.shape[1:]
        self._support_points, self._support_values, self.weights = (
            self._compute_weights(z, f, **kwargs)
        )

        # only compute once

Review comment (suggestion):
Nit: consider not using class variables? Had to check in an interactive session that different instances do indeed not share the value of `_axis`, while mutable class variables do get shared between instances. TBH I'm not sure why and whether this relies on small integers being special. 
So while it works as is, maybe best follow the principle of least surprise.

Code after:
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import warnings
import operator
from types import GenericAlias

import numpy as np
import scipy


__all__ = ["AAA", "FloaterHormannInterpolator"]


class _BarycentricRational:
    """Base class for barycentric representation of a rational function."""

    # generic type compatibility with scipy-stubs
    __class_getitem__ = classmethod(GenericAlias)

    def __init__(self, x, y, axis=0, **kwargs):
        self._axis = axis

        # input validation
        z = np.asarray(x)
        f = np.asarray(y)

        self._input_validation(z, f, **kwargs)

        f = np.moveaxis(f, self._axis, 0)

        # Remove infinite or NaN function values and repeated entries
        to_keep = np.logical_and.reduce(
            ((np.isfinite(f)) & (~np.isnan(f))).reshape(f.shape[0], -1),
            axis=-1
        )
        f = f[to_keep, ...]
        z = z[to_keep]
        z, uni = np.unique(z, return_index=True)
        f = f[uni, ...]

        self._shape = f.shape[1:]
        self._support_points, self._support_values, self.weights = (
            self._compute_weights(z, f, **kwargs)
        )