python 中正在生成复合对象的映射字典

Generating mapping dictionary of composite object in python

我需要复合 class 到 return 实例映射的方法。

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

此解决方案仅在首次调用 as_dict() 方法时有效。当它第二次被调用时,这将不起作用,因为 self.entity 现在将引用字典并且调用 __dict__ 将引发 AttributeError

所以我想出了一个不太有效的解决方案;

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

这可行但效率不高,因为我每次调用该函数时都会对实例进行深层复制。

我的问题是,为什么当我调用 self.entity.__dict__ 时,entity 变成类型 dict 而不是类型 Entity?这背后的机制是什么?还有什么是获取复合对象映射的最有效实现?

正如 jonrsharpe 提到的,这:

mapping_dict = self.__dict__

不创建 self.__dict__ 的副本 - 它仅将本地名称 mapping_dict 绑定到也绑定到 self.__dict__ 的对象(您肯定想 read this有关 python 名称/绑定等的更多信息。

因此下一行:

   mapping_dict['component'] = self.component.__dict__

实际上相当于:

   self.component = self.component.__dict__

这显然不是你想要的。

一个简单的解决方案是从 self.__dict__ 创建一个新的字典。由于 ComponentEntity 都需要这个,更好的解决方案是将其分解为 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  

请注意,这不会考虑计算属性(属性等),只会考虑普通实例属性,但我假设这就是您想要的。