code: def attr_dict(self):
          
          size = mx_uint()
          pairs = ctypes.POINTER(ctypes.c_char_p)()
          f_handle = _LIB.MXSymbolListAttr
          check_call(f_handle(self.handle, ctypes.byref(size), ctypes.byref(pairs)))
          ret = {}
          for i in range(size.value):
              name, key = py_str(pairs[i * 2]).split('$')
              val = py_str(pairs[i * 2 + 1])
              if name not in ret:
                  ret[name] = {}
              ret[name][key] = val
          return ret
docs: Recursively gets all attributes from the symbol and its children.
  
          Example
          -------
          >>> a = mx.sym.Variable('a', attr={'a1':'a2'})
          >>> b = mx.sym.Variable('b', attr={'b1':'b2'})
          >>> c = a+b
          >>> c.attr_dict()
          {'a': {'a1': 'a2'}, 'b': {'b1': 'b2'}}
  
          Returns
          -------
          ret : Dict of str to dict
              There is a key in the returned dict for every child with non-empty attribute set.
              For each symbol, the name of the symbol is its key in the dict
              and the correspond value is that symbol's attribute list (itself a dictionary).