class_docstr: Efficient representation of ``f_1*f_2*...*f_n``.
class_docstr_tok: ["Efficient","representation","of","``","f_1","*","f_2","*","...","*","f_n","``","."]
docstr: Initialize Factors from dict or expr.
  
  Examples
  ========
  
  >>> from sympy.core.exprtools import Factors
  >>> from sympy.abc import x
  >>> from sympy import I
  >>> e = 2*x**3
  >>> Factors(e)
  Factors({2: 1, x: 3})
  >>> Factors(e.as_powers_dict())
  Factors({2: 1, x: 3})
  >>> f = _
  >>> f.factors  # underlying dictionary
  {2: 1, x: 3}
  >>> f.gens  # base of each factor
  frozenset({2, x})
  >>> Factors(0)
  Factors({0: 1})
  >>> Factors(I)
  Factors({I: 1})
  
  Notes
  =====
  
  Although a dictionary can be passed, only minimal checking is
  performed: powers of -1 and I are made canonical.
docstr_tok: ["Initialize","Factors","from","dict","or","expr",".","Examples","========",">",">",">","from","sympy.core.exprtools","import","Factors",">",">",">","from","sympy.abc","import","x",">",">",">","from","sympy","import","I",">",">",">","e","=","2","*","x","*","*","3",">",">",">","Factors","(","e",")","Factors","(","{","2",":","1",",","x",":","3","}",")",">",">",">","Factors","(","e.as_powers_dict","(",")",")","Factors","(","{","2",":","1",",","x",":","3","}",")",">",">",">","f","=","_",">",">",">","f.factors","#","underlying","dictionary","{","2",":","1",",","x",":","3","}",">",">",">","f.gens","#","base","of","each","factor","frozenset","(","{","2",",","x","}",")",">",">",">","Factors","(","0",")","Factors","(","{","0",":","1","}",")",">",">",">","Factors","(","I",")","Factors","(","{","I",":","1","}",")","Notes","=====","Although","a","dictionary","can","be","passed",",","only","minimal","checking","is","performed",":","powers","of","-1","and","I","are","made","canonical","."]
code: def __init__(self, factors=None):  # Factors
      """Initialize Factors from dict or expr.
  
      Examples
      ========
  
      >>> from sympy.core.exprtools import Factors
      >>> from sympy.abc import x
      >>> from sympy import I
      >>> e = 2*x**3
      >>> Factors(e)
      Factors({2: 1, x: 3})
      >>> Factors(e.as_powers_dict())
      Factors({2: 1, x: 3})
      >>> f = _
      >>> f.factors  # underlying dictionary
      {2: 1, x: 3}
      >>> f.gens  # base of each factor
      frozenset({2, x})
      >>> Factors(0)
      Factors({0: 1})
      >>> Factors(I)
      Factors({I: 1})
  
      Notes
      =====
  
      Although a dictionary can be passed, only minimal checking is
      performed: powers of -1 and I are made canonical.
  
      """
      if isinstance(factors, (SYMPY_INTS, float)):
          factors = S(factors)
      if isinstance(factors, Factors):
          factors = factors.factors.copy()
      elif factors in (None, S.One):
          factors = {}
      elif factors is S.Zero or factors == 0:
          factors = {S.Zero: S.One}
      elif isinstance(factors, Number):
          n = factors
          factors = {}
          if n < 0:
              factors[S.NegativeOne] = S.One
              n = -n
          if n is not S.One:
              if n.is_Float or n.is_Integer or n is S.Infinity:
                  factors[n] = S.One
              elif n.is_Rational:
                  # since we're processing Numbers, the denominator is
                  # stored with a negative exponent; all other factors
                  # are left .
                  if n.p != 1:
                      factors[Integer(n.p)] = S.One
                  factors[Integer(n.q)] = S.NegativeOne
              else:
                  raise ValueError(
                      "Expected Float|Rational|Integer, not %s" % n
                  )
      elif isinstance(factors, Basic) and not factors.args:
          factors = {factors: S.One}
      elif isinstance(factors, Expr):
          c, nc = factors.args_cnc()
          i = c.count(I)
          for _ in range(i):
              c.remove(I)
          factors = dict(Mul._from_args(c).as_powers_dict())
          # Handle all rational Coefficients
          for f in list(factors.keys()):
              if isinstance(f, Rational) and not isinstance(f, Integer):
                  p, q = Integer(f.p), Integer(f.q)
                  factors[p] = (
                      factors[p] if p in factors else S.Zero
                  ) + factors[f]
                  factors[q] = (
                      factors[q] if q in factors else S.Zero
                  ) - factors[f]
                  factors.pop(f)
          if i:
              factors[I] = factors.get(I, S.Zero) + i
          if nc:
              factors[Mul(*nc, evaluate=False)] = S.One
      else:
          factors = factors.copy()  # /!\ should be dict-like
  
          # tidy up -/+1 and I exponents if Rational
  
          handle = [k for k in factors if k is I or k in (-1, 1)]
          if handle:
              i1 = S.One
              for k in handle:
                  if not _isnumber(factors[k]):
                      continue
                  i1 *= k ** factors.pop(k)
              if i1 is not S.One:
                  for a in (
                      i1.args if i1.is_Mul else [i1]
                  ):  # at worst, -1.0*I*(-1)**e
                      if a is S.NegativeOne:
                          factors[a] = S.One
                      elif a is I:
                          factors[I] = S.One
                      elif a.is_Pow:
                          factors[a.base] = (
                              factors.get(a.base, S.Zero) + a.exp
                          )
                      elif equal_valued(a, 1):
                          factors[a] = S.One
                      elif equal_valued(a, -1):
                          factors[-a] = S.One
                          factors[S.NegativeOne] = S.One
                      else:
                          raise ValueError(
                              "unexpected factor in i1: %s" % a
                          )
  
      self.factors = factors
      keys = getattr(factors, "keys", None)
      if keys is None:
          raise TypeError("expecting Expr or dictionary")
      self.gens = frozenset(keys())
  
imports: from .add import Add
  from .mul import Mul, _keep_coeff
  from .power import Pow
  from .basic import Basic
  from .expr import Expr
  from .function import expand_power_exp
  from .sympify import sympify
  from .numbers import Rational, Integer, Number, I, equal_valued
  from .singleton import S
  from .sorting import default_sort_key, ordered
  from .symbol import Dummy
  from .traversal import preorder_traversal
  from .coreerrors import NonCommutativeExpression
  from .containers import Tuple, Dict
  from sympy.external.gmpy import SYMPY_INTS
  from sympy.utilities.iterables import common_prefix, common_suffix, variations, iterable, is_sequence
  from collections import defaultdict
  from typing import Tuple
label_desc: Use image node_id 1 to create a new Factors object  with example: obj = Factors(factors)