Repository: sympy/sympy
File: sympy/core/expr.py (Python)

Code before:
        want: type[Add] | type[Mul]
        if hint.get('as_Add', isinstance(self, Add) ):
            want = Add
        else:
            want = Mul

        # sift out deps into symbolic and other and ignore
        # all symbols but those that are in the free symbols
        sym = set()
        other = []
        for d in deps:
            if isinstance(d, Symbol):  # Symbol.is_Symbol is True
                sym.add(d)
            else:
                other.append(d)

        def has(e):
            """return the standard has() if there are no literal symbols, else
            check to see that symbol-deps are in the free symbols."""
            has_other = e.has(*other)
            if not sym:
                return has_other
            return has_other or e.has(*(e.free_symbols & sym))

        if (not issubclass(func, want) or
            not issubclass(func, Add) and not issubclass(func, Mul)):
            if has(self):
                return (want.identity, self)
            else:
                return (self, want.identity)
        else:
            if issubclass(func, Add):
                args = list(self.args)
            else:
                args, nc = self.args_cnc()

        d = sift(args, has)
        depend = d[True]
        indep = d[False]
        if issubclass(func, Add):  # all terms were treated as commutative
            return (func(*indep), _unevaluated_Add(*depend))
        else:  # handle noncommutative by stopping at first dependent term
            for i, n in enumerate(nc):
                if has(n):
                    depend.extend(nc[i:])
                    break
                indep.append(n)
            return func(*indep), _unevaluated_Mul(*depend)

    def as_real_imag(self, deep=True, **hints) -> tuple[Expr, Expr]:
        """Performs complex expansion on 'self' and returns a tuple

Review comment (suggestion):
I would probably just change this to something like:
```python
        if want is Add and not self.is_Add:
            if has(self):
                return (S.Zero, self)
            else:
                return (self, S.Zero)

        elif want is Mul and not self.is_Mul:
            if has(self):
                return (S.One, self)
            else:
                return (self, S.One)
```
That is much easier to understand and will also work for subclasses.

Code after:
        as_coeff_mul
        """
        from .symbol import Symbol
        from .add import _unevaluated_Add
        from .mul import _unevaluated_Mul

        if self is S.Zero:
            return (self, self)

        if as_Add is None:
            as_Add = self.is_Add

        syms, other = _sift_true_false(deps, lambda d: isinstance(d, Symbol))
        syms_set = set(syms)

        if other:
            def has(e):
                return e.has_xfree(syms_set) or e.has(*other)
        else:
            def has(e):
                return e.has_xfree(syms_set)

        if as_Add:
            if not self.is_Add:
                if has(self):
                    return (S.Zero, self)
                else:
                    return (self, S.Zero)

            depend, indep = _sift_true_false(self.args, has)
            return (self.func(*indep), _unevaluated_Add(*depend))

        else:
            if not self.is_Mul:
                if has(self):
                    return (S.One, self)
                else:
                    return (self, S.One)

            args, nc = self.args_cnc()
            depend, indep = _sift_true_false(args, has)

            # handle noncommutative by stopping at first dependent term
            for i, n in enumerate(nc):
                if has(n):
                    depend.extend(nc[i:])
                    break
                indep.append(n)

            return self.func(*indep), _unevaluated_Mul(*depend)