Почему исходный список не копируется?

Почему не скопировался исходный список?

def em(list_data):
    with open('test2.json','r',encoding='utf-8') as file_json:
        data_json = []
        for item in file_json:
            try:
                data_json.append(json.loads(item))
            except Exception as err:
                print(err)
    data_result = []
    copy_list_data = list_data.copy()

    for data in list_data:
        for item in data_json:
            if data['idnp'] in item[0] or data['idnp'] == item[0]:
                data_result.append(item)
                data.clear()
                break
        
    for data in list_data:
        if data.get('idnp'):
            data_result.append(list(data.values()))

    print(copy_list_data)

В первом цикле я достаю из файла все строки. Во втором цикле я добавляю в нужном мне порядке элементы в список data_result и затем то что добавил очищаю. И в list_data остается уже очищенный список и затем то что осталось я добавляю в окончательный список.

Но почему в переменной copy_list_data после того как я очистил список list_data сохраняется очищенный список? Я же скопировал исходный список до очищения

А можно как-то по другому написать данную функцию, без дополнительных циклов и переменных? Объясню, что мне нужно: В файле находятся строки такого вида ["S18D8402100DY", "\u041a\u0410\u041f\u041e\u0422", "Chery", "0", "15", 11604.06, "BRAN", 11922.12, "TKUC", 11951.53, "FRZA", "None"] А в исходном списке list_data есть словари и в каждый словарь имеет уникальный артикул, ключ idnp, пример {'idnp': 'F3102000C1', 'name': '', 'brand': 'LIFAN', 'min_count': 0, 'max_time_delivery': 15, 'count_sell': nan}

В исходном списке находятся словари для парсинга, в результате, после парсинга, данные сохраняются в json'e в файл. Далее я вызываю эту функцию. Но данные которые в исходном списке и файле расходятся. В файле может быть такое, что некоторых записей нету. Поэтому мне нужно получить список, в котором будут недостающие записи из исходного списка. Как это сделать?


Ответы (1 шт):

Автор решения: mkkik

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

Эта проблема решается использованием "глубокого" копирования - создание реальных новых объектов.

from copy import deepcopy

l1 = [['a', 'b'], ['c', 'd']]

l1_c = l1.copy()
l1_dc = deepcopy(l1)

# оригинал и копия ссылаются на один объект в памяти
assert(id(l1[0]) == id(l1_c[0]))

# оригинал и глубокая копия ссылаются на разные объекты в памяти
assert(id(l1[0]) != id(l1_dc[0]))

for l in l1:
    l.clear()

print(l1_c)  # -> [[], []]
print(l1_dc)  # -> [['a', 'b'], ['c', 'd']]
→ Ссылка