<p dir="auto">See SO post<br>
<a href="https://stackoverflow.com/q/46498784/2336654" rel="nofollow">https://stackoverflow.com/q/46498784/2336654</a></p>
<h4 dir="auto">Code Sample, a copy-pastable example if possible</h4>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="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)"><pre class="notranslate"><code class="notranslate">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)
</code></pre></div>
<h4 dir="auto">Problem description</h4>
<p dir="auto">According to <a href="https://pandas.pydata.org/pandas-docs/stable/internals.html#define-original-properties" rel="nofollow">https://pandas.pydata.org/pandas-docs/stable/internals.html#define-original-properties</a><br>
I should be able to define an original property and have it passed on when a new object is constructed.</p>
<p dir="auto">This works</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="s.mul(2).attr

3"><pre class="notranslate"><code class="notranslate">s.mul(2).attr

3
</code></pre></div>
<p dir="auto">While this doesn't</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="s.__mul__(2).attr

0"><pre class="notranslate"><code class="notranslate">s.__mul__(2).attr

0
</code></pre></div>
<h4 dir="auto">Expected Output</h4>
<p dir="auto">I expected both output to be <code class="notranslate">3</code></p>
<h4 dir="auto">Output of <code class="notranslate">pd.show_versions()</code></h4>
<details>
<h2 dir="auto">[paste the output of <code class="notranslate">pd.show_versions()</code> here below this line]<br>
INSTALLED VERSIONS</h2>
<p dir="auto">commit: None<br>
python: 3.6.0.final.0<br>
python-bits: 64<br>
OS: Darwin<br>
OS-release: 16.7.0<br>
machine: x86_64<br>
processor: i386<br>
byteorder: little<br>
LC_ALL: None<br>
LANG: en_US.UTF-8<br>
LOCALE: en_US.UTF-8</p>
<p dir="auto">pandas: 0.20.3<br>
pytest: 3.2.1<br>
pip: 9.0.1<br>
setuptools: 36.3.0<br>
Cython: 0.25.2<br>
numpy: 1.13.1<br>
scipy: 0.18.1<br>
xarray: 0.9.5<br>
IPython: 6.1.0<br>
sphinx: 1.5.1<br>
patsy: 0.4.1<br>
dateutil: 2.6.1<br>
pytz: 2017.2<br>
blosc: None<br>
bottleneck: 1.2.0<br>
tables: 3.3.0<br>
numexpr: 2.6.1<br>
feather: 0.4.0<br>
matplotlib: 2.0.0<br>
openpyxl: 2.4.1<br>
xlrd: 1.0.0<br>
xlwt: 1.2.0<br>
xlsxwriter: 0.9.6<br>
lxml: 3.7.2<br>
bs4: 4.5.3<br>
html5lib: 0.999999999<br>
sqlalchemy: 1.1.5<br>
pymysql: None<br>
psycopg2: None<br>
jinja2: 2.9.6<br>
s3fs: None<br>
pandas_gbq: None<br>
pandas_datareader: 0.4.0</p>
</details>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="#!/bin/env python
&quot;&quot;&quot;
Example bug in derived Pandas Series.

__finalized__ is not called in arithmetic binary operators, but it is in in some booleans cases.

&gt;&gt;&gt; m = MySeries([1, 2, 3], name='test')
&gt;&gt;&gt; m.x = 42
&gt;&gt;&gt; n=m[:2]
&gt;&gt;&gt; n
0    1
1    2
dtype: int64
&gt;&gt;&gt; n.x
42
&gt;&gt;&gt; o=n+1
&gt;&gt;&gt; o
0    2
1    3
dtype: int64
&gt;&gt;&gt; o.x
Traceback (most recent call last):
        ...
AttributeError: 'MySeries' object has no attribute 'x'
&gt;&gt;&gt; m = MySeries([True, False, True], name='test2')
&gt;&gt;&gt; m.x = 42
&gt;&gt;&gt; n=m[:2]
&gt;&gt;&gt; n
0     True
1    False
dtype: bool
&gt;&gt;&gt; n.x
42
&gt;&gt;&gt; o=n ^ True
&gt;&gt;&gt; o
0    False
1     True
dtype: bool
&gt;&gt;&gt; o.x
42
&gt;&gt;&gt; p = n ^ o
&gt;&gt;&gt; p
0    True
1    True
dtype: bool
&gt;&gt;&gt; p.x
42

&quot;&quot;&quot;

import pandas as pd

class MySeries(pd.Series):
    _metadata = ['x']

    @property
    def _constructor(self):
        return MySeries

if __name__ == &quot;__main__&quot;:
    import doctest
    doctest.testmod()
"><pre class="notranslate"><code class="notranslate">#!/bin/env python
"""
Example bug in derived Pandas Series.

__finalized__ is not called in arithmetic binary operators, but it is in in some booleans cases.

&gt;&gt;&gt; m = MySeries([1, 2, 3], name='test')
&gt;&gt;&gt; m.x = 42
&gt;&gt;&gt; n=m[:2]
&gt;&gt;&gt; n
0    1
1    2
dtype: int64
&gt;&gt;&gt; n.x
42
&gt;&gt;&gt; o=n+1
&gt;&gt;&gt; o
0    2
1    3
dtype: int64
&gt;&gt;&gt; o.x
Traceback (most recent call last):
        ...
AttributeError: 'MySeries' object has no attribute 'x'
&gt;&gt;&gt; m = MySeries([True, False, True], name='test2')
&gt;&gt;&gt; m.x = 42
&gt;&gt;&gt; n=m[:2]
&gt;&gt;&gt; n
0     True
1    False
dtype: bool
&gt;&gt;&gt; n.x
42
&gt;&gt;&gt; o=n ^ True
&gt;&gt;&gt; o
0    False
1     True
dtype: bool
&gt;&gt;&gt; o.x
42
&gt;&gt;&gt; p = n ^ o
&gt;&gt;&gt; p
0    True
1    True
dtype: bool
&gt;&gt;&gt; p.x
42

"""

import pandas as pd

class MySeries(pd.Series):
    _metadata = ['x']

    @property
    def _constructor(self):
        return MySeries

if __name__ == "__main__":
    import doctest
    doctest.testmod()

</code></pre></div>
<h4 dir="auto">Expected Output</h4>
<p dir="auto">In all cases, the metadata 'x' should be transferred from the passed values when applying binary operators.<br>
When the right-hand value is a constant, the left-hand value metadata should be used in <strong>finalize</strong> for arithmetic operators, just like it is for Boolean binary operators.<br>
When two series are used in binary operators, some resolution should be possible in <strong>finalize</strong>.<br>
I would pass the second (right-hand) value by calling <strong>finalize</strong>(self, other=other), leaving the resolution to the derived class implementer, but there might be a smarter approach.</p>
<h4 dir="auto">output of <code class="notranslate">pd.show_versions()</code></h4>
<p dir="auto">pd.show_versions()</p>
<h2 dir="auto">INSTALLED VERSIONS</h2>
<p dir="auto">commit: None<br>
python: 2.7.6.final.0<br>
python-bits: 64<br>
OS: Linux<br>
OS-release: 3.19.0-59-generic<br>
machine: x86_64<br>
processor: x86_64<br>
byteorder: little<br>
LC_ALL: None<br>
LANG: en_US.UTF-8</p>
<p dir="auto">pandas: 0.18.1<br>
nose: 1.3.7<br>
pip: None<br>
setuptools: 20.2.2<br>
Cython: 0.24<br>
numpy: 1.11.0<br>
scipy: 0.17.0<br>
statsmodels: 0.6.1<br>
xarray: None<br>
IPython: 4.0.1<br>
sphinx: 1.3.1<br>
patsy: 0.4.0<br>
dateutil: 2.4.2<br>
pytz: 2015.7<br>
blosc: None<br>
bottleneck: 1.0.0<br>
tables: 3.2.2<br>
numexpr: 2.5.2<br>
matplotlib: 1.5.0<br>
openpyxl: 2.2.6<br>
xlrd: 0.9.4<br>
xlwt: 1.0.0<br>
xlsxwriter: 0.7.7<br>
lxml: 3.4.4<br>
bs4: 4.4.1<br>
html5lib: 0.9999999<br>
httplib2: None<br>
apiclient: None<br>
sqlalchemy: 1.0.9<br>
pymysql: None<br>
psycopg2: None<br>
jinja2: 2.8<br>
boto: 2.38.0<br>
pandas_datareader: None</p>