Очень простой подход, не зависящий от версии python, отсутствовал в уже заданных ответах, которые вы можете использовать большую часть времени (по крайней мере, я):
new_list = my_list * 1 #Solution 1 when you are not using nested lists
Однако, если my_list содержит другие контейнеры ( например, вложенных списков), вы должны использовать функцию глубокой печати, как другие, предложенные в ответах выше, из библиотеки копий. Например:
import copy
new_list = copy.deepcopy(my_list) #Solution 2 when you are using nested lists
.Bonus: Если вы не хотите копировать элементы, используйте (ака мелкой копии):
new_list = my_list[:]
Давайте понимать разницу между решением # 1 и Solution # 2
>>> a = range(5)
>>> b = a*1
>>> a,b
([0, 1, 2, 3, 4], [0, 1, 2, 3, 4])
>>> a[2] = 55
>>> a,b
([0, 1, 55, 3, 4], [0, 1, 2, 3, 4])
Как вы можете видеть, решение № 1 отлично работало, когда мы не использовали вложенные списки. Давайте проверим, что произойдет, когда мы применим решение №1 к вложенным спискам.
>>> from copy import deepcopy
>>> a = [range(i,i+4) for i in range(3)]
>>> a
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
>>> b = a*1
>>> c = deepcopy(a)
>>> for i in (a, b, c): print i
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
>>> a[2].append('99')
>>> for i in (a, b, c): print i
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5, 99]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5, 99]] #Solution#1 didn't work in nested list
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]] #Solution #2 - DeepCopy worked in nested list
Существуют важные различия между этими тремя вариантами.
File.open("file").each_line { |line| puts line }
File.open
открывает локальный файл и возвращает файл-объект IO#close
на нем open("file").each_line { |line| puts line }
Kernel.open
смотрит на строку, чтобы решить, что с ней делать.
open(".irbrc").class # => File
open("http://google.com/").class # => StringIO
File.open("http://google.com/") # => Errno::ENOENT: No such file or directory - http://google.com/
Во втором случае объект StringIO
, возвращенный Kernel#open
, фактически содержит содержимое http://google.com/ . Если Kernel#open
возвращает объект File
, он остается открытым, пока вы не назовете IO#close
на нем.
IO.foreach("file") { |line| puts line }
IO.foreach
открывает файл, называет данный блок для каждой прочитанной строки и закрывает файл впоследствии. File.read("file").each { |line| puts line }
Вы не упомянули об этом выборе, но это тот, который я использовал бы в большинстве случаев.
File.read
полностью читает файл и возвращает его как строку. IO.foreach
это дает понять, что вы имеете дело с файлом. В этой ситуации это не удается:
s= File.read("/dev/zero") # => never terminates
s.each …
ri - это инструмент, который показывает вам рубиновую документацию. Вы используете его так же на своей оболочке.
ri File.open
ri open
ri IO.foreach
ri File#each_line
С этим вы можете найти почти все, что я написал здесь, и многое другое.
ri
- RTFM джентльмена. – Fábio Batista 22 February 2011 в 01:30ri File.open
работает. – johannes 8 October 2012 в 09:02File.open
, он будет автоматически закрыт, когда блок завершится, нет необходимости называтьIO#close
– Tombart 5 February 2013 в 23:34