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
, который является неизменным, так что это не приведет к таким проблемам. Но если один из них, скажем, список или объект, имеющий свои собственные атрибуты, он будет.