Каковы варианты клонирования или копирования списка в Python?
В Python 3 мелкая копия может быть выполнена с помощью:
a_copy = a_list.copy()
В Python 2 и 3 вы можете получить мелкую копию с полным фрагментом оригинала:
a_copy = a_list[:]
Объяснение
Существует два семантических способа копирования списка. Неглубокая копия создает новый список тех же объектов, глубокая копия создает новый список, содержащий новые эквивалентные объекты.
Короткая копия списка
Неглубокая копия копирует только сам список, который является контейнером ссылок на объекты в списке. Если объекты, содержащиеся в них, являются изменяемыми и один из них изменен, это изменение будет отражено в обоих списках.
Существуют разные способы сделать это в Python 2 и 3. Пути Python 2 также будут работать в Python 3.
Python 2
В Python 2 , идиоматический способ создания мелкой копии списка состоит из полного фрагмента оригинала:
a_copy = a_list[:]
Вы также можете выполнить одно и то же, передав список через конструктор списка,
a_copy = list(a_list)
, но использование конструктора менее эффективно:
>>> timeit >>> l = range(20) >>> min(timeit.repeat(lambda: l[:])) 0.30504298210144043 >>> min(timeit.repeat(lambda: list(l))) 0.40698814392089844
Python 3
В Python 3 списки получают метод
list.copy
:a_copy = a_list.copy()
В Python 3.5:
>>> import timeit >>> l = list(range(20)) >>> min(timeit.repeat(lambda: l[:])) 0.38448613602668047 >>> min(timeit.repeat(lambda: list(l))) 0.6309100328944623 >>> min(timeit.repeat(lambda: l.copy())) 0.38122922903858125
Создание другого указателя делает not сделать копию
Используя new_list = my_list, тогда изменяет new_list каждый раз, когда изменяется my_list. Почему это?
my_list
- это просто имя, которое указывает на фактический список в памяти. Когда вы скажетеnew_list = my_list
, что вы не делаете копию, вы просто добавляете другое имя, указывающее на этот исходный список в памяти. У нас могут быть подобные проблемы, когда мы делаем копии списков.>>> l = [[], [], []] >>> l_copy = l[:] >>> l_copy [[], [], []] >>> l_copy[0].append('foo') >>> l_copy [['foo'], [], []] >>> l [['foo'], [], []]
Список - это всего лишь массив указателей на содержимое, поэтому мелкая копия просто копирует указатели, поэтому у вас есть два разных списка, но они имеют одинаковое содержимое. Чтобы сделать копии содержимого, вам нужна глубокая копия.
Глубокие копии
Чтобы сделать глубокую копию списка в Python 2 или 3, используйте
deepcopy
в модулеcopy
:import copy a_deep_copy = copy.deepcopy(a_list)
Чтобы продемонстрировать, как это позволяет нам создавать новые под-списки:
>>> import copy >>> l [['foo'], [], []] >>> l_deep_copy = copy.deepcopy(l) >>> l_deep_copy[0].pop() 'foo' >>> l_deep_copy [[], [], []] >>> l [['foo'], [], []]
Итак, мы видим, что глубокий скопированный список - это совсем другой список из оригинала. Вы можете перевернуть свою собственную функцию, но не надо. Вероятно, вы создадите ошибки, которых иначе не было бы, используя функцию глубокой печати стандартной библиотеки.
Не использовать
eval
Вы можете видеть, что это используется как способ to deepcopy, но не делайте этого:
problematic_deep_copy = eval(repr(a_list))
- Это опасно, особенно если вы оцениваете что-то из источника, которому вы не доверяете.
- Это не надежный, если подэлемент, который вы копируете, не имеет представления, которое может быть доказано для воспроизведения эквивалентного элемента.
- Он также менее эффективен.
В 64-битном Python 2.7:
>>> import timeit >>> import copy >>> l = range(10) >>> min(timeit.repeat(lambda: copy.deepcopy(l))) 27.55826997756958 >>> min(timeit.repeat(lambda: eval(repr(l)))) 29.04534101486206
на 64-битном Python 3.5:
>>> import timeit >>> import copy >>> l = list(range(10)) >>> min(timeit.repeat(lambda: copy.deepcopy(l))) 16.84255409205798 >>> min(timeit.repeat(lambda: eval(repr(l)))) 34.813894678023644
Если вы работаете в браузере, вы не можете загружать локальные файлы .
Но довольно просто запустить dev-сервер, в командной строке, просто cd
в каталог с вашими файлами, затем:
python -m SimpleHTTPServer
(или python -m http.server
с помощью python 3)
Теперь в вашем браузере перейдите к localhost:3000
(или :8000
или что-то, что показано на командной строке).
Следующие используются для работы в более старых версиях d3:
var json = {"my": "json"};
d3.json(json, function(json) {
root = json;
root.x0 = h / 2;
root.y0 = 0;
});
Я использовал этот
d3.json("graph.json", function(error, xyz) {
if (error) throw error;
// the rest of my d3 graph code here
}
, чтобы вы могли ссылаться на ваш json-файл, используя переменную xyz, а graph - это имя моего локального json-файла
Добавляя к предыдущим ответам, проще использовать HTTP-сервер, предоставляемый большинством машин Linux / Mac (только с установленным python).
Выполните следующую команду в корне вашего проекта
python -m SimpleHTTPServer
Затем вместо доступа к file://.....index.html
откройте ваш браузер на http://localhost:8080
или в порту, предоставляемом при запуске сервера. Таким образом браузер заставит все файлы в вашем проекте не блокироваться.
Вы не можете легко читать локальные файлы, по крайней мере, не в Chrome, а, возможно, и в других браузерах.
Простейшим обходным путем является простое включение данных JSON в вашем файле сценария, а затем просто избавиться от вашего вызова d3.json
и сохранить код в обратном вызове, который вы передаете ему.
Тогда ваш код будет выглядеть следующим образом:
json = { ... };
root = json;
root.x0 = h / 2;
root.y0 = 0;
...
http://bl.ocks.org/eyaler/10586116 См. этот код, это чтение из файла и создание графика. У меня также была та же проблема, но позже я выяснил, что проблема была в json-файле, который я использовал (дополнительная запятая). Если вы получаете нуль, попробуйте напечатать ошибку, которую вы получаете, как это может быть.
d3.json("filename.json", function(error, graph) {
alert(error)
})
Это работает в firefox, в хром как-то его не печатает ошибку.
d3.json(filename, function(error, data) {...}
(Должен ли я задать отдельный вопрос?) – Ismail Moghul 11 October 2014 в 00:13d3.json
или$.get
; просто ссылайтесь на переменную напрямую. Или я что-то пропустил здесь, чтобы объяснить 13 авитаминов? – James Conkling 18 September 2015 в 01:31d3.json()
берет строку, представляющую путь к файлу. В случае no i>, еслиd3.json()
принимает в качестве первого аргумента объект JSON (или что-то другое, кроме строки). см. здесь . – James Conkling 20 September 2015 в 18:29