Создание словаря сопоставления составного объекта в Python - PullRequest
0 голосов
/ 01 июня 2018

Мне нужен метод в составном классе для возврата сопоставления экземпляра.

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?Какой механизм стоит за этим?А также, какова наиболее эффективная реализация для получения сопоставления составного объекта?

1 Ответ

0 голосов
/ 01 июня 2018

Как упоминает jonrsharpe, это:

mapping_dict = self.__dict__

не создает копию self.__dict__ - он только привязывает локальное имя mapping_dict к объекту, также связанному с self.__dict__ (вы определенно хотите прочитайте это для получения дополнительной информации об именах / привязках Python и т. д.).

Итак, следующая строка:

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

фактически эквивалентна:

   self.component = self.component.__dict__

, что явно не то, что вы хотите.

Простое решение - создать новый dict из self.__dict__.Поскольку это необходимо как для Component, так и для Entity, лучшее решение состоит в том, чтобы выделить это для класса mixin :

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  

Обратите внимание, что для этого не потребуется вычислениеатрибуты (свойства и т. д.) в учетной записи, только простые атрибуты экземпляра, но я предполагаю, что это то, что вы хотите.

...