индексирование списков против копирования - PullRequest
0 голосов
/ 28 августа 2018

У меня есть список с именем mylist

В чем разница между

newlist = mylist

и

newlist = mylist[:]

может показаться, что последний безопаснее использовать, поскольку он не будет мутировать mylist на основании каких-либо манипуляций с newlist

`

Ответы [ 2 ]

0 голосов
/ 28 августа 2018

Первый только создает другое имя для списка. Это все тот же список.

Это означает, что мутирует newlist, также мутирует mylist.

>>> mylist = [1, 2, 3]
>>> newlist = mylist
>>> newlist.append(4)
>>> mylist
[1, 2, 3, 4]

Во втором примере создается копия списка, фактически новый список.

>>> mylist = [1, 2, 3]
>>> newlist = mylist[:]
>>> newlist.append(4)
>>> newlist
[1, 2, 3, 4]
>>> mylist
[1, 2, 3]

У вас мало причин иметь два имени для одного и того же объекта, так как это может сбить с толку и привести к ошибкам мутации.

Ошибка мутации - это когда в какой-то части вашего кода требуется какой-то объект, скажем, функция func1, но предварительно мутировавший в какой-то другой части вашего кода, например, в функцию func2. Если объект в его начальном состоянии ожидался func1, может быть очень утомительно отслеживать, где произошла мутация.

Пример:

obj = [list of data]
same_obj = obj

func2(same_obj) # mutates the object

# hundreds of lines of code

func1(obj) # needs the initial state of the object

В приведенном выше примере было бы лучше передать func2 копию obj. Поскольку многое происходит между первой и последней строками, отследить ошибку мутации может быть очень утомительно.

0 голосов
/ 28 августа 2018

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

Эта строка:

newlist = mylist

это ужасный питон. Поскольку это не «новый список» , поскольку имя переменной предлагает , он просто добавляет другое имя для того же списка.

Это приемлемо:

mylist_again = mylist

Предпочтительнее ли брать фрагмент с mylist[:] или нет, полностью зависит от контекста. Иногда вам нужна копия, иногда вам нужна другая ссылка на существующие данные.

может показаться, что последний безопаснее использовать, поскольку он не будет мутировать mylist, основываясь на каких-либо манипуляциях с newlist

Это не совсем так, поскольку срез является лишь поверхностной копией. Новый список все еще может находиться в состоянии общего доступа:

>>> mylist = [0, [1]]
>>> newlist = mylist[:]
>>> newlist[0] = 123
>>> newlist[1][0] = 456
>>> mylist
[0, [456]]
>>> newlist
[123, [456]]

Опять же, достаточно ли мелкой копии или нет, зависит от данных. Если вы используете вложенные данные, а поверхностной копии недостаточно, или есть изменяемые элементы, которые следует скопировать, вы можете использовать copy.deepcopy.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...