Модуль copy — поверхностное и глубокое копирование объектов
Операция присваивания не копирует объект, он лишь создаёт ссылку на объект. Для изменяемых коллекций, или для коллекций, содержащих изменяемые элементы, часто необходима такая копия, чтобы её можно было изменить, не изменяя оригинал. Данный модуль предоставляет общие (поверхностная и глубокая) операции копирования.
copy.copy(x) — возвращает поверхностную копию x.
copy.deepcopy(x) — возвращает полную копию x.
Исключениеcopy.error — возникает, если объект невозможно скопировать.
Разница между поверхностным и глубоким копированием существенна только для составных объектов, содержащих изменяемые объекты (например, список списков, или словарь, в качестве значений которого — списки или словари):
- Поверхностная копия создает новый составной объект, и затем (по мере возможности) вставляет в него ссылки на объекты, находящиеся в оригинале.
- Глубокая копия создает новый составной объект, и затем рекурсивно вставляет в него копии объектов, находящихся в оригинале.
Для операции глубокого копирования часто возникают две проблемы, которых нет у операции поверхностного копирования:
- Рекурсивные объекты (составные объекты, которые явно или неявно содержат ссылки на себя) могут стать причиной рекурсивного цикла;
- Поскольку глубокая копия копирует всё, она может скопировать слишком много, например, административные структуры данных, которые должны быть разделяемы даже между копиями.
Функция deepcopy решает эти проблемы путем:
- Хранения «memo» словаря объектов, скопированных во время текущего прохода копирования;
- Позволения классам, определенным пользователем, переопределять операцию копирования или набор копируемых компонентов.
Этот модуль не копирует типы вроде модулей, классов, функций, методов, следа в стеке, стековых кадров, файлов, сокетов, окон, и подобных типов.
Поверхностная копия изменяемых объектов также может быть создана методом .copy() у списков (начиная с Python 3.3), присваиванием среза (copied_list = original_list[:]), методом .copy() словарей и множеств. Создавать копию неизменяемых объектов (таких, как, например, строк) необязательно (они же неизменяемые).
Для того, чтобы определить собственную реализацию копирования, класс может определить специальные методы __copy__() и __deepcopy__(). Первый вызывается для реализации операции поверхностного копирования; дополнительных аргументов не передается. Второй вызывается для реализации операции глубокого копирования; ему передается один аргумент, словарь memo. Если реализация __deepcopy__() нуждается в создании глубокой копии компонента, то он должен вызвать функцию deepcopy() с компонентом в качестве первого аргумента и словарем memo в качестве второго аргумента.
Для вставки кода на Python в комментарий заключайте его в теги
Копирование объектов, модуль copy
В Python изменяемые объекты нельзя скопировать, присвоив одну переменной другой, так как в этом случае копируется ссылка на объект, а не он сам. В итоге при изменении объекта через одну переменную, изменения видны через другую. Поэтому используются иные способы копирования, если оно действительно необходимо.
У списков, словарей и некоторых других встроенных типов есть метод copy() , создающий их поверхностную копию. В случае поверхностной копии, если объект является составным, то есть включает другие изменяемые объекты, то они не копируются, а копируются только ссылки на них.
Если же требуется полная копия объекта, следует воспользоваться функцией deepcopy() модуля copy . Кроме этой функции там также есть функция copy() , выполняющая поверхностное копирование, аналогичное методам copy() словарей и списков.
Разницу между copy() и deepcopy() иллюстрирует пример:
>>> import copy >>> nums = [1, 2, 3] >>> data = >>> data >>> data_copy = copy.copy(data) >>> data_deep = copy.deepcopy(data) >>> data_copy >>> data_deep >>> data_copy['a'] += 2 >>> nums[1:1] = [254] >>> data >>> data_copy >>> data_deep
В случае с deepcopy() была создана копия вложенного списка, copy() этого не делает.
Отсутствие переменной у списка вовсе не изменяет ситуацию:
>>> d = >>> c = copy.copy(d) >>> c >>> c[1].append(3) >>> c >>> d
Оператор is проверяет проверяет ссылаются ли две переменные на один объект, оператор == проверяет равенство значений.
>>> d = >>> c = d >>> e = d.copy() >>> d is c True >>> d is e False >>> d == e True
С помощью функций модуля copy можно копировать объекты собственных классов:
import copy class A: def __init__(self): self.lst = [] a = A() a.lst.append(10) b = copy.copy(a) b.lst[0] = 20 print(a.lst, b.lst) print(a is b) print(a) print(b)
[20] [20] False
Как мы видим, несмотря на то, что объекты a и b разные, поле lst обоих ссылается на один и тот же список. Чтобы при копировании объекта список был также скопирован, следует использовать функцию deepcopy() .
Могу ли я просто скопировать модуль для python из старой папки в новую?
Я установил python на новый сервер и мне нужно обойти установление модуля requests. Он есть на другой машине. Можно ли просто скопировать файлы манульно? Будет ли все работать правильно или это не лучшая практика?
Отслеживать
user259379
задан 26 июл 2017 в 12:51
Superluminal Superluminal
938 6 6 серебряных знаков 27 27 бронзовых знаков
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
Pip freeze
По-моему, самое лучшее для новичка и лентяя - это делать pip freeze > requirements.txt , получим список установленных модулей с их версиями. После этого на новой машине делаем pip install -r requirements.txt , и подгружаем нужные нам модули с точно такими же версиями.
Virtualenv
Так же рекомендуется использовать virtualenv — это инструмент, позволяющий создавать виртуальные окружения с пакетами. Можно рассмотреть ее как своего рода "песочницу". Разные "песочницы" имеют разный набор пакетов разных версий. Плюс к этому уходит проблема засорения системы ненужными пакетами, так как "песочницы" можно легко создавать и удалять. В песочницу устанавливаются пакеты, которые необходимы для конкретной реализации. Используя два virtualenv на проект — одного чистого, содержащего минимальный набор зависимостей, и одного, предназначенного для разработки. Думаю, такой подход в любом случае не лишен смысла, так как вряд ли вы захотите тянуть на боевой сервер всевозможные моки и фреймворки для тестирования.
Статья о том как использовать virtualenv .
Python way
Чтобы объявить необходимые зависимости для своего пакета, можно указать их в install_requires в setup.py . И вообще написание для своего проекта setup.py - это лучшая практика, о чем написано в этой документации.
Как копировать модули Python из одной системы в другую?
Если у вас есть свои собственные модули Python, которые вы хотите скопировать, вы можете просто скопировать их и запустить на других системах с установленным Python. Если вы хотите скопировать установленные модули, лучше всего установить ту же версию Python во второй системе. Тогда беги
$ pip freeze > installed_modules.txt
на первой системе, чтобы получить список установленных модулей в файле instal_modules.txt. Теперь скопируйте этот файл во вторую систему. Теперь используйте pip для установки этих модулей, используя:
$ pip install -r installed_modules.txt
Это установит все модули, которые были установлены в первой системе. Это лучший способ, так как простое копирование из одной системы в другую может вызвать проблемы из-за различий в ОС, архитектуре, версиях и т. Д.
