def na_op(x, y): # TODO: # should have guarantees on what x, y can be type-wise # Extension Dtypes are not called here if is_object_dtype(x.dtype): result = comp_method_OBJECT_ARRAY(op, x, y) else: method = getattr(x, op_name) with np.errstate(all="ignore"): result = method(y) if result is NotImplemented: return invalid_comparison(x, y, op) return result
def wrapper(self, other): res_name = get_op_result_name(self, other) # TODO: shouldn't we be applying finalize whenever # not isinstance(other, ABCSeries)? finalizer = (lambda x: x.__finalize__(self) if isinstance(other, (np.ndarray, ABCIndexClass)) else x) if isinstance(other, ABCDataFrame): # pragma: no cover # Defer to DataFrame implementation; fail early return NotImplemented if isinstance(other, ABCSeries) and not self._indexed_same(other): raise ValueError( "Can only compare identically-labeled Series objects") other = lib.item_from_zerodim(other) if isinstance(other, list): # TODO: same for tuples? other = np.asarray(other) if isinstance(other, (np.ndarray, ABCExtensionArray, ABCIndexClass)): # TODO: make this treatment consistent across ops and classes. # We are not catching all listlikes here (e.g. frozenset, tuple) # The ambiguous case is object-dtype. See GH#27803 if len(self) != len(other): raise ValueError("Lengths must match to compare") lvalues = extract_array(self, extract_numpy=True) rvalues = extract_array(other, extract_numpy=True) if should_extension_dispatch(lvalues, rvalues): res_values = dispatch_to_extension_op(op, lvalues, rvalues) elif is_scalar(rvalues) and isna(rvalues): # numpy does not like comparisons vs None if op is operator.ne: res_values = np.ones(len(lvalues), dtype=bool) else: res_values = np.zeros(len(lvalues), dtype=bool) elif is_object_dtype(lvalues.dtype): res_values = comp_method_OBJECT_ARRAY(op, lvalues, rvalues) else: op_name = "__{op}__".format(op=op.__name__) method = getattr(lvalues, op_name) with np.errstate(all="ignore"): res_values = method(rvalues) if res_values is NotImplemented: res_values = invalid_comparison(lvalues, rvalues, op) if is_scalar(res_values): raise TypeError( "Could not compare {typ} type with Series".format( typ=type(rvalues))) result = self._constructor(res_values, index=self.index) result = finalizer(result) # Set the result's name after finalizer is called because finalizer # would set it back to self.name result.name = res_name return result