@@ -787,11 +787,17 @@ def na_op(x, y):
787787
788788 return result
789789
790- fill_int = lambda x : x . fillna ( 0 )
790+ fill_int = lambda x : x
791791
792792 def fill_bool (x , left = None ):
793793 # if `left` is specifically not-boolean, we do not cast to bool
794- x = x .fillna (False )
794+ if x .dtype .kind in ["c" , "f" , "O" ]:
795+ # dtypes that can hold NA
796+ mask = isna (x )
797+ if mask .any ():
798+ x = x .astype (object )
799+ x [mask ] = False
800+
795801 if left is None or is_bool_dtype (left .dtype ):
796802 x = x .astype (bool )
797803 return x
@@ -814,40 +820,35 @@ def wrapper(self, other):
814820 # Defer to DataFrame implementation; fail early
815821 return NotImplemented
816822
817- elif should_extension_dispatch (self , other ):
818- lvalues = extract_array (self , extract_numpy = True )
819- rvalues = extract_array (other , extract_numpy = True )
823+ other = lib .item_from_zerodim (other )
824+ if is_list_like (other ) and not hasattr (other , "dtype" ):
825+ # e.g. list, tuple
826+ other = construct_1d_object_array_from_listlike (other )
827+
828+ lvalues = extract_array (self , extract_numpy = True )
829+ rvalues = extract_array (other , extract_numpy = True )
830+
831+ if should_extension_dispatch (self , rvalues ):
820832 res_values = dispatch_to_extension_op (op , lvalues , rvalues )
821- result = self ._constructor (res_values , index = self .index , name = res_name )
822- return finalizer (result )
823833
824- elif isinstance (other , (ABCSeries , ABCIndexClass )):
825- is_other_int_dtype = is_integer_dtype (other .dtype )
826- other = other if is_other_int_dtype else fill_bool (other , self )
834+ else :
835+ if isinstance (rvalues , (ABCSeries , ABCIndexClass , np .ndarray )):
836+ is_other_int_dtype = is_integer_dtype (rvalues .dtype )
837+ rvalues = rvalues if is_other_int_dtype else fill_bool (rvalues , lvalues )
827838
828- elif is_list_like (other ):
829- # list, tuple, np.ndarray
830- if not isinstance (other , np .ndarray ):
831- other = construct_1d_object_array_from_listlike (other )
839+ else :
840+ # i.e. scalar
841+ is_other_int_dtype = lib .is_integer (rvalues )
832842
833- is_other_int_dtype = is_integer_dtype ( other . dtype )
834- other = type ( self )( other )
835- other = other if is_other_int_dtype else fill_bool ( other , self )
843+ # For int vs int `^`, `|`, `&` are bitwise operators and return
844+ # integer dtypes. Otherwise these are boolean ops
845+ filler = fill_int if is_self_int_dtype and is_other_int_dtype else fill_bool
836846
837- else :
838- # i.e. scalar
839- is_other_int_dtype = lib .is_integer (other )
840-
841- # TODO: use extract_array once we handle EA correctly, see GH#27959
842- ovalues = lib .values_from_object (other )
843-
844- # For int vs int `^`, `|`, `&` are bitwise operators and return
845- # integer dtypes. Otherwise these are boolean ops
846- filler = fill_int if is_self_int_dtype and is_other_int_dtype else fill_bool
847- res_values = na_op (self .values , ovalues )
848- unfilled = self ._constructor (res_values , index = self .index , name = res_name )
849- filled = filler (unfilled )
850- return finalizer (filled )
847+ res_values = na_op (lvalues , rvalues )
848+ res_values = filler (res_values )
849+
850+ result = self ._constructor (res_values , index = self .index , name = res_name )
851+ return finalizer (result )
851852
852853 wrapper .__name__ = op_name
853854 return wrapper
0 commit comments