@MrxAlexo

Как создать новый словарь, не меняя старый?

Имею вот такой список из словарей
self.rows = [
            {'game': '#1', 'players': 'Player vs Player', 'steps': 57, 'round': 7, 'start_ts': 1672989122, 'status':1},
        ]

Я хочу отобразить элементы списка, добавив новое значение time, но не удаляя из основного списка значения start_ts и status:
rows = self.rows
rows[0].pop('start_ts')
rows[0].pop('status')
rows[0]['time'] = '00:00'

Теперь хочу вывести новый список с новыми значениями:
print(rows)
Получаю:
{'game': '#1', 'players': 'Player vs Player', 'steps': 57, 'round': 7, 'time': '00:00'}


НО! В тоже время изменяется из self.rows, который является другим списком. При выводе старого списка получаю:
print(self.rows)
Получаю:
{'game': '#1', 'players': 'Player vs Player', 'steps': 57, 'round': 7, 'time': '00:00'}


Почему так происходит и как это исправить?
  • Вопрос задан
  • 91 просмотр
Решения вопроса 2
Vindicar
@Vindicar
RTFM!
rows = self.rows
НО! В тоже время изменяется из self.rows, который является другим списком.

Не является. Твой оператор просто присвоил переменной rows ссылку на тот же самый список, что и self.rows.
Это легко проверить оператором is или сравнением id():
print(rows is self.rows, id(rows) == id(self.rows))  # True True

Более того, если ты только скопируешь сам список:
rows = self.rows.copy()
То всё ещё поймаешь проблемы, так как скопируются ссылки на элементы, а не их значения:
print(rows is self.rows, id(rows) == id(self.rows))  # False False
print(rows[0] is self.rows[0], id(rows[0]) == id(self.rows[0]))  # True True

Тебе нужно сделать глубокую копию (deepcopy). Это можно сделать вручную, так как у тебя всего два уровня вложенности (список-словарь):
rows = [rowdict.copy() for rowdict in self.rows]
Для более глубоких уровней есть функция copy.deepcopy(), но у неё есть свои подводные камни. Цитата:
Two problems often exist with deep copy operations that don’t exist with shallow copy operations:
Recursive objects (compound objects that, directly or indirectly, contain a reference to themselves) may cause a recursive loop.
Because deep copy copies everything it may copy too much, such as data which is intended to be shared between copies.
Ответ написан
Комментировать
@humoured
Вы всё на свете найдёте в коробке с карандашами
Так происходит, потому что присвоение значения переменной rows = self.rows не является дублированием исходного массива. Нужно использовать deepcopy().
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы