Some operations that do not match user attributes in the Series subclass

According to https://pandas.pydata.org/pandas-docs/stable/internals.html
I must be able to trim the pandas series

My mcve

from pandas import Series


class Xseries(Series):
    _metadata = ['attr']

    @property
    def _constructor(self):
        return Xseries

    def __init__(self, *args, **kwargs):
        self.attr = kwargs.pop('attr', 0)
        super().__init__(*args, **kwargs)

s = Xseries([1, 2, 3], attr=3)

Note that the attribute attr:

s.attr

3

However, when I multiply by 2

(s * 2).attr

0

This is the default value. Therefore, it was attrnot transmitted. You may ask, maybe this is not intentional behavior? I think this is according to the documentation https://pandas.pydata.org/pandas-docs/stable/internals.html#define-original-properties

And if we use the method mul, it works

s.mul(2).attr

3

And it’s not (it’s the same as s * 2)

s.__mul__(2).attr

0

I wanted to pass this transferred to SO before I created the problem on github. This is mistake?

?

s * 2 attr .

+4
2

inspect.getsourcelines mul __mul__, , .

s.mul(2).attr - , __finalize__ , .

, , , , attr?

, __mul__ __finalize__.

from pandas import Series


class Xseries(Series):
    _metadata = ['attr']

    @property
    def _constructor(self):
        return Xseries

    def __init__(self, *args, **kwargs):
        self.attr = kwargs.pop('attr', 0)
        super().__init__(*args, **kwargs)

    def __mul__(self, other):
        internal_result = super().__mul__(other)
        return internal_result.__finalize__(self)

s = Xseries([1, 2, 3], attr=3)

, attr .

from pandas import Series


class Xseries(Series):
    _metadata = ['attr']

    @property
    def _constructor(self):
        return Xseries

    def __init__(self, *args, **kwargs):
        self.attr = kwargs.pop('attr', 0)
        super().__init__(*args, **kwargs)

    def __mul__(self, other):
        internal_result = super().__mul__(other)
        if hasattr(other, "attr"):
            internal_result.attr = self.attr * other.attr
        else:
            internal_result.attr = self.attr * other
        return internal_result

s = Xseries([1, 2, 3], attr=3)
+2

, @chrisb .


@chrisb , .

Matthiasha , , .

from pandas import Series


class Xseries(Series):
    _metadata = ['attr']

    @property
    def _constructor(self):
        def _c(*args, **kwargs):
            # workaround for https://github.com/pandas-dev/pandas/issues/13208
            return Xseries(*args, **kwargs).__finalize__(self)
        return _c

    def __init__(self, *args, **kwargs):
        self.attr = kwargs.pop('attr', 0)
        super().__init__(*args, **kwargs)

:

(Xseries([1, 2, 3], attr=3) * 2).attr

3
0

Source: https://habr.com/ru/post/1686673/


All Articles