Python, как сохранить новые объекты в списке без дублирования

Высокоуровневая картина моей программы

  • Цель: разобрать файл XML и сохранить текст в похожие объекты Python
  • проблема: каждый раз, когда я создаю новый объект python и добавляю его в список, вместо создания нового объекта, кажется, добавляется ссылка на предыдущие объекты.

Краткое описание того, какой должна быть моя предполагаемая структура:

список приложений, каждое из которых содержит список подключений

app1: 
     connection1
     connection2
app2:
     connection3
     connection4
     connection5

так вот краткое изложение того, что он должен делать... так вот моя основная функция:

def main(self):
    root = get_xml_root()
    root.get_applications()
    for application in root.applications:
        application.get_connections()           ## this is where the memory goes bad!!!
        for connection in application.connections:
              connection.do_something()

Насколько я знаю, что есть проблема с памятью:

  • Когда я изменяю одну вещь в одном списке соединений, которые принадлежат конкретному приложению, соединения в другом приложении также будут меняться.
  • Я распечатал места памяти для соединений и обнаружил, что есть дубликаты ссылок (см. Распечатки памяти)

Распечатки памяти

  • когда я распечатывал местоположения приложений, я получил следующее (это не красиво, но вы можете видеть, что по крайней мере адреса разные):

generator_libraries.data_extraction.extraction.Application_XML экземпляр в 0x15a07e8 - ячейка памяти = 22677480 generator_libraries.data_extraction.extraction.Application_XML экземпляр в 0x15a0758 - расположение памяти = 22677336 генератор.Application_XML экземпляр в 0x15a0878 - расположение в памяти = 22677624 generator_libraries.data_extraction.extraction. - расположение в памяти = 22677840 экземпляр generator_libraries.data_extraction.extraction.Application_XML в 0x15a0998 - расположение в памяти = 22677912 экземпляр generator_libraries.data_extraction.extraction.Application_XML в 0x15a09e0 - m расположение emory = 22677984 generator_libraries.data_extraction.extraction.Application_XML экземпляр в 0x15a0a28 - расположение в памяти = 22678056

  • когда я распечатал места подключения для 3 разных приложений, я получил следующее (вы можете увидеть дублирование между адресами):

    • приложение 1::
    • ячейка памяти = 22721168
    • ячейка памяти = 22721240
    • ячейка памяти = 22721024
    • ячейка памяти = 22721600
    • ячейка памяти = 22721672

    • app2:

    • ячейка памяти = 22721240
    • ячейка памяти = 22721672
    • ячейка памяти = 22721600
    • ячейка памяти = 22721168
    • ячейка памяти = 22722104
    • ячейка памяти = 22722176

Выводы из анализа памяти. Кажется, что каждый раз, когда я создаю новый объект соединения и добавляю его в свой список "соединений", вместо создания нового объекта он берет ссылку на память из моих предыдущих объектов.

Более подробный вид кода проблемной функции

class Application_XML(XML_Element_Class):
    name = None
    connections=copy.deepcopy([])
    xml_element=None
    def get_connections(self):
        xml_connections = self.get_xml_children()
        for xml_connection in xml_connections:
            connection = None       ## reset the connection variable
            connection = Connection_XML(xml_connection)
            connection.unique_ID = connection_count
            self.connections.append(copy.deepcopy(connection))
            del connection      ## reset where its pointing to
            connection_count+=1
        self.log_debugging_info_on_connection_memory()   ### this is where I look at memory locations

Класс, который делает то же самое... но работает

class Root_XML(XML_Element_Class):
    applications = copy.deepcopy([])
    def get_applications(self):
        xml_applications = self.get_xml_children()
        for xml_application in xml_applications:
            self.applications.append(Application_XML(xml_application))
        self.log_application_memory_information()

Если это поможет, вот класс соединения:

class Connection_XML(XML_Element_Class):
    ### members
    name = None
    type = None
    ID = None
    max_size = None
    queue_size = None
    direction = None
    def do_something(self):
        pass

Заключительные слова

Я попробовал почти все приемы в книге с точки зрения альтернативных способов создания объектов, уничтожения их после того, как я их сделал... но пока ничего не помогло. Я чувствую, что за ответом может быть важная концепция памяти Python... но после всех моих поисков в Интернете, ничто не пролило свет на ответ.

Пожалуйста, если вы можете помочь, это было бы здорово!!! Спасибо:)

1 ответ

Решение

Я не думаю, что проблема связана с той частью, на которую вы смотрите, а скорее с Connection_XML учебный класс:

class Connection_XML(XML_Element_Class):
    ### members
    name = None
    type = None
    ID = None
    max_size = None
    queue_size = None
    direction = None
    def do_something(self):
        pass

Все эти члены являются атрибутами класса. Там один name разделяется каждым Connection_XML Например, один typeи т. д. Итак, даже если все ваши экземпляры являются уникальными объектами, изменение одного из них приводит к их изменению.

Вы хотите атрибуты экземпляра - отдельный nameи т. д. для каждого экземпляра. То, как вы это делаете, это просто динамическое создание атрибутов, обычно в __init__ метод:

class Connection_XML(XML_Element_Class):
    def __init__(self):
        self.name = None
        self.type = None
        self.ID = None
        self.max_size = None
        self.queue_size = None
        self.direction = None
    def do_something(self):
        pass

Трудно быть уверенным, что это твоя проблема без реального SSCCE. В этом игрушечном примере все атрибуты имеют значение None, который является неизменным, так что это не приведет к таким проблемам. Но если один из них, скажем, список или объект, имеющий свои собственные атрибуты, он будет.

Другие вопросы по тегам