code: def get_el_sp(obj):
      
      if isinstance(obj, (Element, Specie, DummySpecie)):
          return obj
  
      if isinstance(obj, (list, tuple)):
          return [get_el_sp(o) for o in obj]
  
      try:
          c = float(obj)
          i = int(c)
          i = i if i == c else None
      except (ValueError, TypeError):
          i = None
  
      if i is not None:
          return Element.from_Z(i)
  
      try:
          return Specie.from_string(obj)
      except (ValueError, KeyError):
          try:
              return Element(obj)
          except (ValueError, KeyError):
              try:
                  return DummySpecie.from_string(obj)
              except:
                  raise ValueError("Can't parse Element or String from type"
                                   " %s: %s." % (type(obj), obj))
docs: Utility method to get an Element or Specie from an input obj.
      If obj is in itself an element or a specie, it is returned automatically.
      If obj is an int or a string representing an integer, the Element
      with the atomic number obj is returned.
      If obj is a string, Specie parsing will be attempted (e.g., Mn2+), failing
      which Element parsing will be attempted (e.g., Mn), failing which
      DummyElement parsing will be attempted.
  
      Args:
          obj (Element/Specie/str/int): An arbitrary object.  Supported objects
              are actual Element/Specie objects, integers (representing atomic
              numbers) or strings (element symbols or species strings).
  
      Returns:
          Specie or Element, with a bias for the maximum number of properties
          that can be determined.
  
      Raises:
          ValueError if obj cannot be converted into an Element or Specie.