Q:

Generating mapping dictionary of composite object in python

I need a method in a composite class to return the mapping of the instance.
class Component:
    def __init___(self, a, b):
        self.a = a
        self.b = b

class Entity:
   def __init__(self, component, c, d):
       self.component= component
       self.c = c
       self.d = d

   def as_dict(self):
       mapping_dict = self.__dict__
       mapping_dict['component'] = self.component.__dict__
       return mapping_dict

This solution will only work once when as_dict() method is called for the first time. When it's called for the second time, this would not work since self.entity will now refer to a dictionary and calling __dict__ on it will raise AttributeError. 
So I came up with a not so efficient solution;
def as_dict(self):
    temp_1 = temp_2 = deepcopy(self)
    mapping_dict = temp_1.__dict__
    mapping_dict['component'] = temp_2.component.__dict__
    return mapping_dict

This works but not so efficient because I am making a deepcopy of the instance every time I call the function. 
My question is, why when I call self.entity.__dict__, entity becomes type dict instead of type Entity? What is the mechanism behind this? And also whats the most efficient implementation to obtain a mapping of a composite object?

A:

As jonrsharpe mentions, this:
mapping_dict = self.__dict__

does not create a copy of self.__dict__ - it only binds the local name mapping_dict to the object also bound to self.__dict__ (you definitly want to read this for more about python names / bindings etc).
So this next line:
   mapping_dict['component'] = self.component.__dict__

is actually the equivalent of:
   self.component = self.component.__dict__

which is obviously not what you want.
A simple solution is to create a new dict from self.__dict__. Since we need this for both  Component and Entity, the better solution is to factor this out to a mixin class:
class AsDictMixin(object):
    def as_dict(self):
        return {
          k:(v.as_dict() if isinstance(v, AsDictMixin) else v) 
          for k, v in self.__dict__.items()
          }

class Component(AsDictMixin):
    def __init___(self, a, b):
        self.a = a
        self.b = b        

class Entity(AsDictMixin):
    def __init__(self, component, c, d):
       self.component= component
       self.c = c
       self.d = d  

Note that this won't take computed attributes (properties etc) in account, only plain instance attributes, but I assume that it's what you want.

