code: def apart_list(f, x=None, dummies=None, **options):
      """
      Compute partial fraction decomposition of a rational function
      and return the result in structured form.
  
      Given a rational function ``f`` compute the partial fraction decomposition
      of ``f``. Only Bronstein's full partial fraction decomposition algorithm
      is supported by this method. The return value is highly structured and
      perfectly suited for further algorithmic treatment rather than being
      human-readable. The function returns a tuple holding three elements:
  
      * The first item is the common coefficient, free of the variable `x` used
        for decomposition. (It is an element of the base field `K`.)
  
      * The second item is the polynomial part of the decomposition. This can be
        the zero polynomial. (It is an element of `K[x]`.)
  
      * The third part itself is a list of quadruples. Each quadruple
        has the following elements in this order:
  
        - The (not necessarily irreducible) polynomial `D` whose roots `w_i` appear
          in the linear denominator of a bunch of related fraction terms. (This item
          can also be a list of explicit roots. However, at the moment ``apart_list``
          never returns a result this way, but the related ``assemble_partfrac_list``
          function accepts this format as input.)
  
        - The numerator of the fraction, written as a function of the root `w`
  
        - The linear denominator of the fraction *excluding its power exponent*,
          written as a function of the root `w`.
  
        - The power to which the denominator has to be raised.
  
      On can always rebuild a plain expression by using the function ``assemble_partfrac_list``.
  
      Examples
      ========
  
      A first example:
  
      >>> from sympy.polys.partfrac import apart_list, assemble_partfrac_list
      >>> from sympy.abc import x, t
  
      >>> f = (2*x**3 - 2*x) / (x**2 - 2*x + 1)
      >>> pfd = apart_list(f)
      >>> pfd
      (1,
      Poly(2*x + 4, x, domain='ZZ'),
      [(Poly(_w - 1, _w, domain='ZZ'), Lambda(_a, 4), Lambda(_a, -_a + x), 1)])
  
      >>> assemble_partfrac_list(pfd)
      2*x + 4 + 4/(x - 1)
  
      Second example:
  
      >>> f = (-2*x - 2*x**2) / (3*x**2 - 6*x)
      >>> pfd = apart_list(f)
      >>> pfd
      (-1,
      Poly(2/3, x, domain='QQ'),
      [(Poly(_w - 2, _w, domain='ZZ'), Lambda(_a, 2), Lambda(_a, -_a + x), 1)])
  
      >>> assemble_partfrac_list(pfd)
      -2/3 - 2/(x - 2)
  
      Another example, showing symbolic parameters:
  
      >>> pfd = apart_list(t/(x**2 + x + t), x)
      >>> pfd
      (1,
      Poly(0, x, domain='ZZ[t]'),
      [(Poly(_w**2 + _w + t, _w, domain='ZZ[t]'),
      Lambda(_a, -2*_a*t/(4*t - 1) - t/(4*t - 1)),
      Lambda(_a, -_a + x),
      1)])
  
      >>> assemble_partfrac_list(pfd)
      RootSum(_w**2 + _w + t, Lambda(_a, (-2*_a*t/(4*t - 1) - t/(4*t - 1))/(-_a + x)))
  
      This example is taken from Bronstein's original paper:
  
      >>> f = 36 / (x**5 - 2*x**4 - 2*x**3 + 4*x**2 + x - 2)
      >>> pfd = apart_list(f)
      >>> pfd
      (1,
      Poly(0, x, domain='ZZ'),
      [(Poly(_w - 2, _w, domain='ZZ'), Lambda(_a, 4), Lambda(_a, -_a + x), 1),
      (Poly(_w**2 - 1, _w, domain='ZZ'), Lambda(_a, -3*_a - 6), Lambda(_a, -_a + x), 2),
      (Poly(_w + 1, _w, domain='ZZ'), Lambda(_a, -4), Lambda(_a, -_a + x), 1)])
  
      >>> assemble_partfrac_list(pfd)
      -4/(x + 1) - 3/(x + 1)**2 - 9/(x - 1)**2 + 4/(x - 2)
  
      See also
      ========
  
      apart, assemble_partfrac_list
  
      References
      ==========
  
      .. [1] [Bronstein93]_
  
      """
      allowed_flags(options, [])
  
      f = sympify(f)
  
      if f.is_Atom:
          return f
      else:
          P, Q = f.as_numer_denom()
  
      options = set_defaults(options, extension=True)
      (P, Q), opt = parallel_poly_from_expr((P, Q), x, **options)
  
      if P.is_multivariate:
          raise NotImplementedError(
              "multivariate partial fraction decomposition"
          )
  
      common, P, Q = P.cancel(Q)
  
      poly, P = P.div(Q, auto=True)
      P, Q = P.rat_clear_denoms(Q)
  
      polypart = poly
  
      if dummies is None:
  
          def dummies(name):
              d = Dummy(name)
              while True:
                  yield d
  
          dummies = dummies("w")
  
      rationalpart = apart_list_full_decomposition(P, Q, dummies)
  
      return (common, polypart, rationalpart)
  
file_path: sympy/sympy/polys/partfrac.py
imports: from sympy.core import S, Add, sympify, Function, Lambda, Dummy
  from sympy.core.traversal import preorder_traversal
  from sympy.polys import Poly, RootSum, cancel, factor
  from sympy.polys.polyerrors import PolynomialError
  from sympy.polys.polyoptions import allowed_flags, set_defaults
  from sympy.polys.polytools import parallel_poly_from_expr
  from sympy.utilities import numbered_symbols, take, xthreaded, public
label_desc: Use image node_id 4 for calling a global function with example usage: apart_list(f, x, dummies) and returns: common,  polypart,  rationalpart, f