|
9 | 9 | from pandas._libs import index as libindex
|
10 | 10 | from pandas._libs.lib import no_default
|
11 | 11 | from pandas._typing import Label
|
12 |
| -import pandas.compat as compat |
13 | 12 | from pandas.compat.numpy import function as nv
|
14 | 13 | from pandas.util._decorators import Appender, cache_readonly, doc
|
15 | 14 |
|
@@ -812,83 +811,95 @@ def any(self, *args, **kwargs) -> bool:
|
812 | 811 |
|
813 | 812 | # --------------------------------------------------------------------
|
814 | 813 |
|
815 |
| - @classmethod |
816 |
| - def _add_numeric_methods_binary(cls): |
817 |
| - """ add in numeric methods, specialized to RangeIndex """ |
818 |
| - |
819 |
| - def _make_evaluate_binop(op, step=False): |
820 |
| - """ |
821 |
| - Parameters |
822 |
| - ---------- |
823 |
| - op : callable that accepts 2 params |
824 |
| - perform the binary op |
825 |
| - step : callable, optional, default to False |
826 |
| - op to apply to the step parm if not None |
827 |
| - if False, use the existing step |
828 |
| - """ |
829 |
| - |
830 |
| - @unpack_zerodim_and_defer(op.__name__) |
831 |
| - def _evaluate_numeric_binop(self, other): |
832 |
| - if isinstance(other, ABCTimedeltaIndex): |
833 |
| - # Defer to TimedeltaIndex implementation |
834 |
| - return NotImplemented |
835 |
| - elif isinstance(other, (timedelta, np.timedelta64)): |
836 |
| - # GH#19333 is_integer evaluated True on timedelta64, |
837 |
| - # so we need to catch these explicitly |
838 |
| - return op(self._int64index, other) |
839 |
| - elif is_timedelta64_dtype(other): |
840 |
| - # Must be an np.ndarray; GH#22390 |
841 |
| - return op(self._int64index, other) |
842 |
| - |
843 |
| - other = extract_array(other, extract_numpy=True) |
844 |
| - attrs = self._get_attributes_dict() |
845 |
| - |
846 |
| - left, right = self, other |
| 814 | + def _arith_method(self, other, op, step=False): |
| 815 | + """ |
| 816 | + Parameters |
| 817 | + ---------- |
| 818 | + other : Any |
| 819 | + op : callable that accepts 2 params |
| 820 | + perform the binary op |
| 821 | + step : callable, optional, default to False |
| 822 | + op to apply to the step parm if not None |
| 823 | + if False, use the existing step |
| 824 | + """ |
| 825 | + |
| 826 | + if isinstance(other, ABCTimedeltaIndex): |
| 827 | + # Defer to TimedeltaIndex implementation |
| 828 | + return NotImplemented |
| 829 | + elif isinstance(other, (timedelta, np.timedelta64)): |
| 830 | + # GH#19333 is_integer evaluated True on timedelta64, |
| 831 | + # so we need to catch these explicitly |
| 832 | + return op(self._int64index, other) |
| 833 | + elif is_timedelta64_dtype(other): |
| 834 | + # Must be an np.ndarray; GH#22390 |
| 835 | + return op(self._int64index, other) |
| 836 | + |
| 837 | + other = extract_array(other, extract_numpy=True) |
| 838 | + attrs = self._get_attributes_dict() |
| 839 | + |
| 840 | + left, right = self, other |
847 | 841 |
|
848 |
| - try: |
849 |
| - # apply if we have an override |
850 |
| - if step: |
851 |
| - with np.errstate(all="ignore"): |
852 |
| - rstep = step(left.step, right) |
| 842 | + try: |
| 843 | + # apply if we have an override |
| 844 | + if step: |
| 845 | + with np.errstate(all="ignore"): |
| 846 | + rstep = step(left.step, right) |
| 847 | + |
| 848 | + # we don't have a representable op |
| 849 | + # so return a base index |
| 850 | + if not is_integer(rstep) or not rstep: |
| 851 | + raise ValueError |
| 852 | + |
| 853 | + else: |
| 854 | + rstep = left.step |
| 855 | + |
| 856 | + with np.errstate(all="ignore"): |
| 857 | + rstart = op(left.start, right) |
| 858 | + rstop = op(left.stop, right) |
| 859 | + |
| 860 | + result = type(self)(rstart, rstop, rstep, **attrs) |
853 | 861 |
|
854 |
| - # we don't have a representable op |
855 |
| - # so return a base index |
856 |
| - if not is_integer(rstep) or not rstep: |
857 |
| - raise ValueError |
| 862 | + # for compat with numpy / Int64Index |
| 863 | + # even if we can represent as a RangeIndex, return |
| 864 | + # as a Float64Index if we have float-like descriptors |
| 865 | + if not all(is_integer(x) for x in [rstart, rstop, rstep]): |
| 866 | + result = result.astype("float64") |
858 | 867 |
|
859 |
| - else: |
860 |
| - rstep = left.step |
| 868 | + return result |
861 | 869 |
|
862 |
| - with np.errstate(all="ignore"): |
863 |
| - rstart = op(left.start, right) |
864 |
| - rstop = op(left.stop, right) |
| 870 | + except (ValueError, TypeError, ZeroDivisionError): |
| 871 | + # Defer to Int64Index implementation |
| 872 | + return op(self._int64index, other) |
| 873 | + # TODO: Do attrs get handled reliably? |
865 | 874 |
|
866 |
| - result = type(self)(rstart, rstop, rstep, **attrs) |
| 875 | + @unpack_zerodim_and_defer("__add__") |
| 876 | + def __add__(self, other): |
| 877 | + return self._arith_method(other, operator.add) |
867 | 878 |
|
868 |
| - # for compat with numpy / Int64Index |
869 |
| - # even if we can represent as a RangeIndex, return |
870 |
| - # as a Float64Index if we have float-like descriptors |
871 |
| - if not all(is_integer(x) for x in [rstart, rstop, rstep]): |
872 |
| - result = result.astype("float64") |
| 879 | + @unpack_zerodim_and_defer("__radd__") |
| 880 | + def __radd__(self, other): |
| 881 | + return self._arith_method(other, ops.radd) |
873 | 882 |
|
874 |
| - return result |
| 883 | + @unpack_zerodim_and_defer("__sub__") |
| 884 | + def __sub__(self, other): |
| 885 | + return self._arith_method(other, operator.sub) |
875 | 886 |
|
876 |
| - except (ValueError, TypeError, ZeroDivisionError): |
877 |
| - # Defer to Int64Index implementation |
878 |
| - return op(self._int64index, other) |
879 |
| - # TODO: Do attrs get handled reliably? |
| 887 | + @unpack_zerodim_and_defer("__rsub__") |
| 888 | + def __rsub__(self, other): |
| 889 | + return self._arith_method(other, ops.rsub) |
880 | 890 |
|
881 |
| - name = f"__{op.__name__}__" |
882 |
| - return compat.set_function_name(_evaluate_numeric_binop, name, cls) |
| 891 | + @unpack_zerodim_and_defer("__mul__") |
| 892 | + def __mul__(self, other): |
| 893 | + return self._arith_method(other, operator.mul, step=operator.mul) |
883 | 894 |
|
884 |
| - cls.__add__ = _make_evaluate_binop(operator.add) |
885 |
| - cls.__radd__ = _make_evaluate_binop(ops.radd) |
886 |
| - cls.__sub__ = _make_evaluate_binop(operator.sub) |
887 |
| - cls.__rsub__ = _make_evaluate_binop(ops.rsub) |
888 |
| - cls.__mul__ = _make_evaluate_binop(operator.mul, step=operator.mul) |
889 |
| - cls.__rmul__ = _make_evaluate_binop(ops.rmul, step=ops.rmul) |
890 |
| - cls.__truediv__ = _make_evaluate_binop(operator.truediv, step=operator.truediv) |
891 |
| - cls.__rtruediv__ = _make_evaluate_binop(ops.rtruediv, step=ops.rtruediv) |
| 895 | + @unpack_zerodim_and_defer("__rmul__") |
| 896 | + def __rmul__(self, other): |
| 897 | + return self._arith_method(other, ops.rmul, step=ops.rmul) |
892 | 898 |
|
| 899 | + @unpack_zerodim_and_defer("__truediv__") |
| 900 | + def __truediv__(self, other): |
| 901 | + return self._arith_method(other, operator.truediv, step=operator.truediv) |
893 | 902 |
|
894 |
| -RangeIndex._add_numeric_methods() |
| 903 | + @unpack_zerodim_and_defer("__rtruediv__") |
| 904 | + def __rtruediv__(self, other): |
| 905 | + return self._arith_method(other, ops.rtruediv, step=ops.rtruediv) |
0 commit comments