Skip to content

Commit b72a049

Browse files
committed
REF: Enhance _construct_result method to accept 'other' parameter for improved attribute handling
1 parent e9c3e91 commit b72a049

File tree

4 files changed

+22
-31
lines changed

4 files changed

+22
-31
lines changed

pandas/core/base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,9 +1480,9 @@ def _arith_method(self, other, op):
14801480
with np.errstate(all="ignore"):
14811481
result = ops.arithmetic_op(lvalues, rvalues, op)
14821482

1483-
return self._construct_result(result, name=res_name)
1483+
return self._construct_result(result, name=res_name, other=other)
14841484

1485-
def _construct_result(self, result, name):
1485+
def _construct_result(self, result, name, other=None):
14861486
"""
14871487
Construct an appropriately-wrapped result from the ArrayLike result
14881488
of an arithmetic-like operation.

pandas/core/frame.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7882,7 +7882,7 @@ def _cmp_method(self, other, op):
78827882

78837883
# See GH#4537 for discussion of scalar op behavior
78847884
new_data = self._dispatch_frame_op(other, op, axis=axis)
7885-
return self._construct_result(new_data)
7885+
return self._construct_result(new_data, other=other)
78867886

78877887
def _arith_method(self, other, op):
78887888
if not getattr(self, "attrs", None) and getattr(other, "attrs", None):
@@ -7898,7 +7898,7 @@ def _arith_method(self, other, op):
78987898

78997899
with np.errstate(all="ignore"):
79007900
new_data = self._dispatch_frame_op(other, op, axis=axis)
7901-
return self._construct_result(new_data)
7901+
return self._construct_result(new_data, other=other)
79027902

79037903
_logical_method = _arith_method
79047904

@@ -8275,12 +8275,9 @@ def _flex_arith_method(
82758275

82768276
new_data = self._dispatch_frame_op(other, op)
82778277

8278-
if not getattr(self, "attrs", None) and getattr(other, "attrs", None):
8279-
self.__finalize__(other)
8278+
return self._construct_result(new_data, other=other)
82808279

8281-
return self._construct_result(new_data)
8282-
8283-
def _construct_result(self, result) -> DataFrame:
8280+
def _construct_result(self, result, other=None) -> DataFrame:
82848281
"""
82858282
Wrap the result of an arithmetic, comparison, or logical operation.
82868283
@@ -8292,6 +8289,8 @@ def _construct_result(self, result) -> DataFrame:
82928289
-------
82938290
DataFrame
82948291
"""
8292+
if not getattr(self, "attrs", None) and getattr(other, "attrs", None):
8293+
self.__finalize__(other)
82958294
out = self._constructor(result, copy=False).__finalize__(self)
82968295
# Pin columns instead of passing to constructor for compat with
82978296
# non-unique columns case
@@ -8316,11 +8315,8 @@ def _flex_cmp_method(self, other, op, *, axis: Axis = "columns", level=None):
83168315

83178316
self, other = self._align_for_op(other, axis, flex=True, level=level)
83188317

8319-
if not getattr(self, "attrs", None) and getattr(other, "attrs", None):
8320-
self.__finalize__(other)
8321-
83228318
new_data = self._dispatch_frame_op(other, op, axis=axis)
8323-
return self._construct_result(new_data)
8319+
return self._construct_result(new_data, other=other)
83248320

83258321
@Appender(ops.make_flex_doc("eq", "dataframe"))
83268322
def eq(self, other, axis: Axis = "columns", level=None) -> DataFrame:

pandas/core/indexes/base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7148,10 +7148,10 @@ def _logical_method(self, other, op):
71487148
rvalues = extract_array(other, extract_numpy=True, extract_range=True)
71497149

71507150
res_values = ops.logical_op(lvalues, rvalues, op)
7151-
return self._construct_result(res_values, name=res_name)
7151+
return self._construct_result(res_values, name=res_name, other=other)
71527152

71537153
@final
7154-
def _construct_result(self, result, name):
7154+
def _construct_result(self, result, name, other=None):
71557155
if isinstance(result, tuple):
71567156
return (
71577157
Index(result[0], name=name, dtype=result[0].dtype),

pandas/core/series.py

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5850,9 +5850,6 @@ def to_period(
58505850
def _cmp_method(self, other, op):
58515851
res_name = ops.get_op_result_name(self, other)
58525852

5853-
if not getattr(self, "attrs", None) and getattr(other, "attrs", None):
5854-
self.__finalize__(other)
5855-
58565853
if isinstance(other, Series) and not self._indexed_same(other):
58575854
raise ValueError("Can only compare identically-labeled Series objects")
58585855

@@ -5861,24 +5858,20 @@ def _cmp_method(self, other, op):
58615858

58625859
res_values = ops.comparison_op(lvalues, rvalues, op)
58635860

5864-
return self._construct_result(res_values, name=res_name)
5861+
return self._construct_result(res_values, name=res_name, other=other)
58655862

58665863
def _logical_method(self, other, op):
5867-
if not getattr(self, "attrs", None) and getattr(other, "attrs", None):
5868-
self.attrs = other.attrs
58695864
res_name = ops.get_op_result_name(self, other)
58705865
self, other = self._align_for_op(other, align_asobject=True)
58715866

58725867
lvalues = self._values
58735868
rvalues = extract_array(other, extract_numpy=True, extract_range=True)
58745869

58755870
res_values = ops.logical_op(lvalues, rvalues, op)
5876-
return self._construct_result(res_values, name=res_name)
5871+
return self._construct_result(res_values, name=res_name, other=other)
58775872

58785873
def _arith_method(self, other, op):
58795874
self, other = self._align_for_op(other)
5880-
if not getattr(self, "attrs", None) and getattr(other, "attrs", None):
5881-
self.attrs = other.attrs
58825875
return base.IndexOpsMixin._arith_method(self, other, op)
58835876

58845877
def _align_for_op(self, right, align_asobject: bool = False):
@@ -5938,14 +5931,14 @@ def _binop(self, other: Series, func, level=None, fill_value=None) -> Series:
59385931

59395932
name = ops.get_op_result_name(self, other)
59405933

5941-
if not getattr(this, "attrs", None) and getattr(other, "attrs", None):
5942-
this.__finalize__(other)
5943-
5944-
out = this._construct_result(result, name)
5934+
out = this._construct_result(result, name, other)
59455935
return cast(Series, out)
59465936

59475937
def _construct_result(
5948-
self, result: ArrayLike | tuple[ArrayLike, ArrayLike], name: Hashable
5938+
self,
5939+
result: ArrayLike | tuple[ArrayLike, ArrayLike],
5940+
name: Hashable,
5941+
other=None,
59495942
) -> Series | tuple[Series, Series]:
59505943
"""
59515944
Construct an appropriately-labelled Series from the result of an op.
@@ -5960,11 +5953,13 @@ def _construct_result(
59605953
Series
59615954
In the case of __divmod__ or __rdivmod__, a 2-tuple of Series.
59625955
"""
5956+
if not getattr(self, "attrs", None) and getattr(other, "attrs", None):
5957+
self.__finalize__(other)
59635958
if isinstance(result, tuple):
59645959
# produced by divmod or rdivmod
59655960

5966-
res1 = self._construct_result(result[0], name=name)
5967-
res2 = self._construct_result(result[1], name=name)
5961+
res1 = self._construct_result(result[0], name=name, other=other)
5962+
res2 = self._construct_result(result[1], name=name, other=other)
59685963

59695964
# GH#33427 assertions to keep mypy happy
59705965
assert isinstance(res1, Series)

0 commit comments

Comments
 (0)