Skip to content

Commit f452a69

Browse files
jbrockmendeljreback
authored andcommitted
CLN: streamline Series _construct_result calls (#28637)
1 parent 762b89c commit f452a69

File tree

2 files changed

+40
-27
lines changed

2 files changed

+40
-27
lines changed

pandas/core/ops/__init__.py

+39-23
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,20 @@
55
"""
66
import datetime
77
import operator
8-
from typing import Tuple
8+
from typing import Tuple, Union
99

1010
import numpy as np
1111

1212
from pandas._libs import Timedelta, Timestamp, lib
1313
from pandas.util._decorators import Appender
1414

1515
from pandas.core.dtypes.common import is_list_like, is_timedelta64_dtype
16-
from pandas.core.dtypes.generic import ABCDataFrame, ABCIndexClass, ABCSeries
16+
from pandas.core.dtypes.generic import (
17+
ABCDataFrame,
18+
ABCExtensionArray,
19+
ABCIndexClass,
20+
ABCSeries,
21+
)
1722
from pandas.core.dtypes.missing import isna
1823

1924
from pandas.core.construction import extract_array
@@ -436,13 +441,37 @@ def _align_method_SERIES(left, right, align_asobject=False):
436441
return left, right
437442

438443

439-
def _construct_result(left, result, index, name, dtype=None):
444+
def _construct_result(
445+
left: ABCSeries,
446+
result: Union[np.ndarray, ABCExtensionArray],
447+
index: ABCIndexClass,
448+
name,
449+
):
440450
"""
441-
If the raw op result has a non-None name (e.g. it is an Index object) and
442-
the name argument is None, then passing name to the constructor will
443-
not be enough; we still need to override the name attribute.
451+
Construct an appropriately-labelled Series from the result of an op.
452+
453+
Parameters
454+
----------
455+
left : Series
456+
result : ndarray or ExtensionArray
457+
index : Index
458+
name : object
459+
460+
Returns
461+
-------
462+
Series
463+
In the case of __divmod__ or __rdivmod__, a 2-tuple of Series.
444464
"""
445-
out = left._constructor(result, index=index, dtype=dtype)
465+
if isinstance(result, tuple):
466+
# produced by divmod or rdivmod
467+
return (
468+
_construct_result(left, result[0], index=index, name=name),
469+
_construct_result(left, result[1], index=index, name=name),
470+
)
471+
472+
# We do not pass dtype to ensure that the Series constructor
473+
# does inference in the case where `result` has object-dtype.
474+
out = left._constructor(result, index=index)
446475
out = out.__finalize__(left)
447476

448477
# Set the result's name after __finalize__ is called because __finalize__
@@ -451,15 +480,6 @@ def _construct_result(left, result, index, name, dtype=None):
451480
return out
452481

453482

454-
def _construct_divmod_result(left, result, index, name, dtype=None):
455-
"""divmod returns a tuple of like indexed series instead of a single series.
456-
"""
457-
return (
458-
_construct_result(left, result[0], index=index, name=name, dtype=dtype),
459-
_construct_result(left, result[1], index=index, name=name, dtype=dtype),
460-
)
461-
462-
463483
def _arith_method_SERIES(cls, op, special):
464484
"""
465485
Wrapper function for Series arithmetic operations, to avoid
@@ -468,9 +488,6 @@ def _arith_method_SERIES(cls, op, special):
468488
str_rep = _get_opstr(op)
469489
op_name = _get_op_name(op, special)
470490
eval_kwargs = _gen_eval_kwargs(op_name)
471-
construct_result = (
472-
_construct_divmod_result if op in [divmod, rdivmod] else _construct_result
473-
)
474491

475492
def wrapper(left, right):
476493
if isinstance(right, ABCDataFrame):
@@ -482,9 +499,7 @@ def wrapper(left, right):
482499
lvalues = extract_array(left, extract_numpy=True)
483500
result = arithmetic_op(lvalues, right, op, str_rep, eval_kwargs)
484501

485-
# We do not pass dtype to ensure that the Series constructor
486-
# does inference in the case where `result` has object-dtype.
487-
return construct_result(left, result, index=left.index, name=res_name)
502+
return _construct_result(left, result, index=left.index, name=res_name)
488503

489504
wrapper.__name__ = op_name
490505
return wrapper
@@ -553,6 +568,7 @@ def flex_wrapper(self, other, level=None, fill_value=None, axis=0):
553568
# validate axis
554569
if axis is not None:
555570
self._get_axis_number(axis)
571+
556572
if isinstance(other, ABCSeries):
557573
return self._binop(other, op, level=level, fill_value=fill_value)
558574
elif isinstance(other, (np.ndarray, list, tuple)):
@@ -564,7 +580,7 @@ def flex_wrapper(self, other, level=None, fill_value=None, axis=0):
564580
if fill_value is not None:
565581
self = self.fillna(fill_value)
566582

567-
return self._constructor(op(self, other), self.index).__finalize__(self)
583+
return op(self, other)
568584

569585
flex_wrapper.__name__ = name
570586
return flex_wrapper

pandas/core/series.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -2738,10 +2738,7 @@ def _binop(self, other, func, level=None, fill_value=None):
27382738
result = func(this_vals, other_vals)
27392739

27402740
name = ops.get_op_result_name(self, other)
2741-
if func.__name__ in ["divmod", "rdivmod"]:
2742-
ret = ops._construct_divmod_result(self, result, new_index, name)
2743-
else:
2744-
ret = ops._construct_result(self, result, new_index, name)
2741+
ret = ops._construct_result(self, result, new_index, name)
27452742
return ret
27462743

27472744
def combine(self, other, func, fill_value=None):

0 commit comments

Comments
 (0)