Уже есть много ответов, которые расскажут вам, как сделать правильную копию, но никто из них не говорит, почему ваша оригинальная «копия» не удалась.
Python не сохраняет значения в переменных; он связывает имена с объектами. Ваше исходное назначение взяло объект, на который ссылается my_list
, и связал его с new_list
. Независимо от того, какое имя вы используете, остается только один список, поэтому изменения, сделанные при обращении к нему как my_list
, будут сохраняться при обращении к нему как new_list
. Каждый из других ответов на этот вопрос дает вам различные способы создания нового объекта для привязки к new_list
.
Каждый элемент списка действует как имя, поскольку каждый элемент связывается не исключительно с объектом. Неглубокая копия создает новый список, элементы которого привязываются к тем же объектам, что и раньше.
new_list = list(my_list) # or my_list[:], but I prefer this syntax
# is simply a shorter way of:
new_list = [element for element in my_list]
Чтобы сделать копию списка еще на один шаг, скопируйте каждый объект, на который ссылается ваш список, и привяжите эти копии элементов в новый список.
import copy
# each element must have __copy__ defined for this...
new_list = [copy.copy(element) for element in my_list]
Это еще не глубокая копия, потому что каждый элемент списка может ссылаться на другие объекты, точно так же, как список привязан к его элементам. Чтобы рекурсивно скопировать каждый элемент в списке, а затем каждый другой объект, на который ссылаются каждый элемент, и т. Д .: выполните глубокую копию.
import copy
# each element must have __deepcopy__ defined for this...
new_list = copy.deepcopy(my_list)
Для получения дополнительной информации о копировании в окне [gg] см. документацию .
В то время как нормальное правило состоит в том, чтобы всегда вызывать Dispose()
во всех реализациях IDisposable
, Task
и Task<T>
часто являются одним из случаев, когда лучше разрешить финализатору это.
Причина Task реализует IDisposable
в основном из-за внутреннего WaitHandle. Это необходимо для правильной работы задач и используется только в случае продолжения задачи. Если продолжения не существует, метод Dispose Dispose не имеет реального эффекта - поэтому в этом случае это не требуется.
Как сказано, в большинстве случаев, когда есть продолжение задачи, это часто очень, очень трудно написать свой код таким образом, чтобы вы могли правильно вызвать Dispose (). Использование операторов обычно не работает с экземплярами Task, так как вызов Task обычно является асинхронным по своей природе. Очень легко избавиться от задачи слишком рано, особенно при использовании оператора using.
Если в вашем случае относительно просто сохранить ссылку на Задачу и правильно вызвать Dispose () , Я бы сделал это. Однако, если это приведет к тому, что ваша логика станет намного сложнее, я обычно делаю вид, что Task не является IDisposable
и разрешает его очищать в финализаторе для задачи.
Для более подробной информации я бы рекомендовал прочитать этот поток на форумах MSDN , где Стивен Тууб описывает, почему Task реализует IDisposable в деталях, и дает аналогичные рекомендации моему предложению выше.