@@ -310,6 +310,45 @@ def names(df: FrameT) -> Sequence[str]:
310310 return self .selectors ._selector .from_callables (series , names , context = self )
311311 return self ._to_expr () & other
312312
313+ @overload # type: ignore[override]
314+ def __xor__ (self , other : Self ) -> Self : ...
315+ @overload
316+ def __xor__ (
317+ self , other : CompliantExpr [FrameT , SeriesOrExprT ]
318+ ) -> CompliantExpr [FrameT , SeriesOrExprT ]: ...
319+ def __xor__ (
320+ self , other : SelectorOrExpr [FrameT , SeriesOrExprT ]
321+ ) -> SelectorOrExpr [FrameT , SeriesOrExprT ]:
322+ if self ._is_selector (other ):
323+
324+ def series (df : FrameT ) -> Sequence [SeriesOrExprT ]:
325+ lhs_names , rhs_names = _eval_lhs_rhs (df , self , other )
326+ return [
327+ * (
328+ x
329+ for x , name in zip (self (df ), lhs_names , strict = True )
330+ if name not in rhs_names
331+ ),
332+ * (
333+ x
334+ for x , name in zip (other (df ), rhs_names , strict = True )
335+ if name not in lhs_names
336+ ),
337+ ]
338+
339+ def names (df : FrameT ) -> Sequence [str ]:
340+ lhs_names , rhs_names = _eval_lhs_rhs (df , self , other )
341+ return [
342+ * (x for x in lhs_names if x not in rhs_names ),
343+ * (x for x in rhs_names if x not in lhs_names ),
344+ ]
345+
346+ return self .selectors ._selector .from_callables (series , names , context = self )
347+ msg = (
348+ f"unsupported operand type(s) for op: ('Selector' ^ '{ type (other ).__name__ } ')"
349+ )
350+ raise TypeError (msg )
351+
313352 def __invert__ (self ) -> CompliantSelector [FrameT , SeriesOrExprT ]:
314353 return self .selectors .all () - self
315354
0 commit comments