code: def remove_keys(d, keys=None, use_wildcards=True,
                  list_of_dicts=False, deepcopy=True):
      
      keys = [] if keys is None else keys
      list_of_dicts = '__list__' if list_of_dicts else None
  
      def is_in(a, bs):
          if use_wildcards:
              for b in bs:
                  try:
                      if a == b:
                          return True
                      if fnmatch(a, b):
                          return True
                  except Exception:
                      pass
              return False
          else:
              try:
                  return a in bs
              except Exception:
                  return False
  
      if not hasattr(d, 'items'):
          return d
      else:
          dic = flatten(d, list_of_dicts=list_of_dicts)
          new_dic = {}
          for key, value in dic.items():
              new_key = tuple([i for i in key if not is_in(i, keys)])
              if not new_key:
                  continue
              try:
                  if new_key[-1].startswith(list_of_dicts):
                      continue
              except Exception:
                  pass
              new_dic[new_key] = value
          return unflatten(
              new_dic, list_of_dicts=list_of_dicts, deepcopy=deepcopy)
docs: remove certain keys from nested dict, retaining preceeding paths
  
      Parameters
      ----------
      keys: list
      use_wildcards : bool
          if true, can use * (matches everything)
          and ? (matches any single character)
      list_of_dicts: bool
          treat list of dicts as additional branches
      deepcopy: bool
  
      Examples
      --------
  
      >>> from pprint import pprint
      >>> d = {1:{"a":"A"},"a":{"b":"B"}}
      >>> pprint(remove_keys(d,['a']))
      {1: 'A', 'b': 'B'}
  
      >>> pprint(remove_keys({'abc':1},['a*'],use_wildcards=False))
      {'abc': 1}
      >>> pprint(remove_keys({'abc':1},['a*'],use_wildcards=True))
      {}