code: def symbols(names, *, cls=Symbol, **args) -> Any:
      r"""
      Transform strings into instances of :class:`Symbol` class.
  
      :func:`symbols` function returns a sequence of symbols with names taken
      from ``names`` argument, which can be a comma or whitespace delimited
      string, or a sequence of strings::
  
          >>> from sympy import symbols, Function
  
          >>> x, y, z = symbols('x,y,z')
          >>> a, b, c = symbols('a b c')
  
      The type of output is dependent on the properties of input arguments::
  
          >>> symbols('x')
          x
          >>> symbols('x,')
          (x,)
          >>> symbols('x,y')
          (x, y)
          >>> symbols(('a', 'b', 'c'))
          (a, b, c)
          >>> symbols(['a', 'b', 'c'])
          [a, b, c]
          >>> symbols({'a', 'b', 'c'})
          {a, b, c}
  
      If an iterable container is needed for a single symbol, set the ``seq``
      argument to ``True`` or terminate the symbol name with a comma::
  
          >>> symbols('x', seq=True)
          (x,)
  
      To reduce typing, range syntax is supported to create indexed symbols.
      Ranges are indicated by a colon and the type of range is determined by
      the character to the right of the colon. If the character is a digit
      then all contiguous digits to the left are taken as the nonnegative
      starting value (or 0 if there is no digit left of the colon) and all
      contiguous digits to the right are taken as 1 greater than the ending
      value::
  
          >>> symbols('x:10')
          (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9)
  
          >>> symbols('x5:10')
          (x5, x6, x7, x8, x9)
          >>> symbols('x5(:2)')
          (x50, x51)
  
          >>> symbols('x5:10,y:5')
          (x5, x6, x7, x8, x9, y0, y1, y2, y3, y4)
  
          >>> symbols(('x5:10', 'y:5'))
          ((x5, x6, x7, x8, x9), (y0, y1, y2, y3, y4))
  
      If the character to the right of the colon is a letter, then the single
      letter to the left (or 'a' if there is none) is taken as the start
      and all characters in the lexicographic range *through* the letter to
      the right are used as the range::
  
          >>> symbols('x:z')
          (x, y, z)
          >>> symbols('x:c')  # null range
          ()
          >>> symbols('x(:c)')
          (xa, xb, xc)
  
          >>> symbols(':c')
          (a, b, c)
  
          >>> symbols('a:d, x:z')
          (a, b, c, d, x, y, z)
  
          >>> symbols(('a:d', 'x:z'))
          ((a, b, c, d), (x, y, z))
  
      Multiple ranges are supported; contiguous numerical ranges should be
      separated by parentheses to disambiguate the ending number of one
      range from the starting number of the next::
  
          >>> symbols('x:2(1:3)')
          (x01, x02, x11, x12)
          >>> symbols(':3:2')  # parsing is from left to right
          (00, 01, 10, 11, 20, 21)
  
      Only one pair of parentheses surrounding ranges are removed, so to
      include parentheses around ranges, double them. And to include spaces,
      commas, or colons, escape them with a backslash::
  
          >>> symbols('x((a:b))')
          (x(a), x(b))
          >>> symbols(r'x(:1\,:2)')  # or r'x((:1)\,(:2))'
          (x(0,0), x(0,1))
  
      All newly created symbols have assumptions set according to ``args``::
  
          >>> a = symbols('a', integer=True)
          >>> a.is_integer
          True
  
          >>> x, y, z = symbols('x,y,z', real=True)
          >>> x.is_real and y.is_real and z.is_real
          True
  
      Despite its name, :func:`symbols` can create symbol-like objects like
      instances of Function or Wild classes. To achieve this, set ``cls``
      keyword argument to the desired type::
  
          >>> symbols('f,g,h', cls=Function)
          (f, g, h)
  
          >>> type(_[0])
          <class 'sympy.core.function.UndefinedFunction'>
  
      """
      result = []
  
      if isinstance(names, str):
          marker = 0
          splitters = r"\,", r"\:", r"\ "
          literals: list[tuple[str, str]] = []
          for splitter in splitters:
              if splitter in names:
                  while chr(marker) in names:
                      marker += 1
                  lit_char = chr(marker)
                  marker += 1
                  names = names.replace(splitter, lit_char)
                  literals.append((lit_char, splitter[1:]))
  
          def literal(s):
              if literals:
                  for c, l in literals:
                      s = s.replace(c, l)
              return s
  
          names = names.strip()
          as_seq = names.endswith(",")
          if as_seq:
              names = names[:-1].rstrip()
          if not names:
              raise ValueError("no symbols given")
  
          # split on commas
          names = [n.strip() for n in names.split(",")]
          if not all(n for n in names):
              raise ValueError("missing symbol between commas")
          # split on spaces
          for i in range(len(names) - 1, -1, -1):
              names[i : i + 1] = names[i].split()
  
          seq = args.pop("seq", as_seq)
  
          for name in names:
              if not name:
                  raise ValueError("missing symbol")
  
              if ":" not in name:
                  symbol = cls(literal(name), **args)
                  result.append(symbol)
                  continue
  
              split: list[str] = _range.split(name)
              split_list: list[list[str]] = []
              # remove 1 layer of bounding parentheses around ranges
              for i in range(len(split) - 1):
                  if (
                      i
                      and ":" in split[i]
                      and split[i] != ":"
                      and split[i - 1].endswith("(")
                      and split[i + 1].startswith(")")
                  ):
                      split[i - 1] = split[i - 1][:-1]
                      split[i + 1] = split[i + 1][1:]
              for s in split:
                  if ":" in s:
                      if s.endswith(":"):
                          raise ValueError("missing end range")
                      a, b = s.split(":")
                      if b[-1] in string.digits:
                          a_i = 0 if not a else int(a)
                          b_i = int(b)
                          split_list.append(
                              [str(c) for c in range(a_i, b_i)]
                          )
                      else:
                          a = a or "a"
                          split_list.append(
                              [
                                  string.ascii_letters[c]
                                  for c in range(
                                      string.ascii_letters.index(a),
                                      string.ascii_letters.index(b) + 1,
                                  )
                              ]
                          )  # inclusive
                      if not split_list[-1]:
                          break
                  else:
                      split_list.append([s])
              else:
                  seq = True
                  if len(split_list) == 1:
                      names = split_list[0]
                  else:
                      names = ["".join(s) for s in product(*split_list)]
                  if literals:
                      result.extend(
                          [cls(literal(s), **args) for s in names]
                      )
                  else:
                      result.extend([cls(s, **args) for s in names])
  
          if not seq and len(result) <= 1:
              if not result:
                  return ()
              return result[0]
  
          return tuple(result)
      else:
          for name in names:
              result.append(symbols(name, cls=cls, **args))
  
          return type(names)(result)
  
imports: from __future__ import annotations
  from .assumptions import StdFactKB, _assume_defined
  from .basic import Basic, Atom
  from .cache import cacheit
  from .containers import Tuple
  from .expr import Expr, AtomicExpr
  from .function import AppliedUndef, FunctionClass
  from .kind import NumberKind, UndefinedKind
  from .logic import fuzzy_bool
  from .singleton import S
  from .sorting import ordered
  from .sympify import sympify
  from sympy.logic.boolalg import Boolean
  from sympy.utilities.iterables import sift, is_sequence
  from sympy.utilities.misc import filldedent
  import string
  import re
  import random
  from itertools import product
  from typing import Any
label_desc: Use image node_id 4 for calling a global function with example usage: symbols(names) and returns: tuple, type, s, result, 