<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def FanOut(self, obj, parent=None):
 """Expand values from various attribute types. Strings are returned as is. Dictionaries are returned with a key string, and an expanded set of values. Other iterables are expanded until they flatten out. Other items are returned in string format. Args: obj: The object to expand out. parent: The parent object: Used to short-circuit infinite recursion. Returns: a list of expanded values as strings. """

    # Catch cases where RDFs are iterable but return themselves.
    if parent and obj == parent:
      results = [utils.SmartUnicode(obj).strip()]
    elif isinstance(obj, (string_types, rdf_structs.EnumNamedValue)):
      results = [utils.SmartUnicode(obj).strip()]
    elif isinstance(obj, rdf_protodict.DataBlob):
      results = self.FanOut(obj.GetValue())
    elif isinstance(obj, (collections.Mapping, rdf_protodict.Dict)):
      results = []
      # rdf_protodict.Dict only has items, not iteritems.
      for k, v in iteritems(obj):
        expanded_v = [utils.SmartUnicode(r) for r in self.FanOut(v)]
        results.append("%s:%s" % (utils.SmartUnicode(k), ",".join(expanded_v)))
    elif isinstance(obj, (collections.Iterable,
                          rdf_structs.RepeatedFieldHelper)):
      results = []
      for rslt in [self.FanOut(o, obj) for o in obj]:
        results.extend(rslt)
    else:
      results = [utils.SmartUnicode(obj).strip()]
    return results