5
5
"""
6
6
import datetime
7
7
import operator
8
- from typing import Tuple
8
+ from typing import Tuple , Union
9
9
10
10
import numpy as np
11
11
12
12
from pandas ._libs import Timedelta , Timestamp , lib
13
13
from pandas .util ._decorators import Appender
14
14
15
15
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
+ )
17
22
from pandas .core .dtypes .missing import isna
18
23
19
24
from pandas .core .construction import extract_array
@@ -436,13 +441,37 @@ def _align_method_SERIES(left, right, align_asobject=False):
436
441
return left , right
437
442
438
443
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
+ ):
440
450
"""
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.
444
464
"""
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 )
446
475
out = out .__finalize__ (left )
447
476
448
477
# Set the result's name after __finalize__ is called because __finalize__
@@ -451,15 +480,6 @@ def _construct_result(left, result, index, name, dtype=None):
451
480
return out
452
481
453
482
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
-
463
483
def _arith_method_SERIES (cls , op , special ):
464
484
"""
465
485
Wrapper function for Series arithmetic operations, to avoid
@@ -468,9 +488,6 @@ def _arith_method_SERIES(cls, op, special):
468
488
str_rep = _get_opstr (op )
469
489
op_name = _get_op_name (op , special )
470
490
eval_kwargs = _gen_eval_kwargs (op_name )
471
- construct_result = (
472
- _construct_divmod_result if op in [divmod , rdivmod ] else _construct_result
473
- )
474
491
475
492
def wrapper (left , right ):
476
493
if isinstance (right , ABCDataFrame ):
@@ -482,9 +499,7 @@ def wrapper(left, right):
482
499
lvalues = extract_array (left , extract_numpy = True )
483
500
result = arithmetic_op (lvalues , right , op , str_rep , eval_kwargs )
484
501
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 )
488
503
489
504
wrapper .__name__ = op_name
490
505
return wrapper
@@ -553,6 +568,7 @@ def flex_wrapper(self, other, level=None, fill_value=None, axis=0):
553
568
# validate axis
554
569
if axis is not None :
555
570
self ._get_axis_number (axis )
571
+
556
572
if isinstance (other , ABCSeries ):
557
573
return self ._binop (other , op , level = level , fill_value = fill_value )
558
574
elif isinstance (other , (np .ndarray , list , tuple )):
@@ -564,7 +580,7 @@ def flex_wrapper(self, other, level=None, fill_value=None, axis=0):
564
580
if fill_value is not None :
565
581
self = self .fillna (fill_value )
566
582
567
- return self . _constructor ( op (self , other ), self . index ). __finalize__ ( self )
583
+ return op (self , other )
568
584
569
585
flex_wrapper .__name__ = name
570
586
return flex_wrapper
0 commit comments