code: def __search_obj(self,
                       obj,
                       item,
                       parent,
                       parents_ids=frozenset({}),
                       is_namedtuple=False):
          
          found = False
          if obj == item:
              found = True
              # We report the match but also continue inside the match to see if there are
              # furthur matches inside the `looped` object.
              self.__report(report_key='matched_values', key=parent, value=obj)
  
          try:
              if is_namedtuple:
                  obj = obj._asdict()
              else:
                  # Skip magic methods. Slightly hacky, but unless people are defining
                  # new magic methods they want to search, it should work fine.
                  obj = {i: getattr(obj, i) for i in dir(obj)
                         if not (i.startswith('__') and i.endswith('__'))}
          except AttributeError:
              try:
                  obj = {i: getattr(obj, i) for i in obj.__slots__}
              except AttributeError:
                  if not found:
                      self['unprocessed'].append("%s" % parent)
  
                  return
  
          self.__search_dict(
              obj, item, parent, parents_ids, print_as_attribute=True)
docs: Search objects