Чтобы избежать плохого влияния на исходный объект, вам в основном нужен вариант copy.deepcopy
... слегка подправленный, потому что вам нужно превратить генераторы и итераторы в списки (глубокое копирование в любом случае не приведет к глубокому копированию генераторов). Обратите внимание, что некоторый эффект на исходный объект, к сожалению, неизбежен, потому что генераторы и итераторы «исчерпаны» как побочный эффект итерации по ним (будь то превращение их в списки или для любых других целей). ) - следовательно, просто невозможно и оставить исходный объект в покое и , превратив этот генератор или другой итератор в список в результате "варианта с глубокой копией".
Модуль copy
, к сожалению, не написан для настройки, поэтому альтернативные варианты: копирование-вставка-редактирование или тонкое (вздох) обезьяна-патч, основанное на (двойном вздохе) переменной приватного модуля _deepcopy_dispatch
(что означает, что ваша исправленная версия может не выдержать обновления версии Python, скажем, с 2.6 до 2.7, гипотетически). Кроме того, обезьяна-патч должна быть удалена после каждого использования eagerize
(во избежание влияния на другие варианты использования deepcopy
). Итак, давайте предположим, что мы выбрали вместо этого маршрут копирования-вставки-редактирования.
Скажем, мы начинаем с самой последней версии, той, которая онлайн здесь . Конечно, вам нужно переименовать модуль; переименуйте внешне видимую функцию от deepcopy
до eagerize
в строке 145; существенное изменение в строках 161-165, которые в указанной версии, аннотированные, являются:
161 : copier = _deepcopy_dispatch.get(cls)
162 : if copier:
163 : y = copier(x, memo)
164 : else:
165 : tim_one 18729 try:
Нам нужно вставить между строками 163 и 164 логику «в противном случае, если это итеративно, разверните ее в список (т. Е. Используйте функцию _deepcopy_list
в качестве копира». Таким образом, эти строки становятся:
161 : copier = _deepcopy_dispatch.get(cls)
162 : if copier:
163 : y = copier(x, memo)
elif hasattr(cls, '__iter__'):
y = _deepcopy_list(x, memo)
164 : else:
165 : tim_one 18729 try:
Вот и все: только две добавленные строки. Обратите внимание, что я оставил только исходные номера строк, чтобы было совершенно ясно, , где , именно эти две строки должны быть вставлены, а не пронумерованы две новые строки. Вам также необходимо переименовать другие экземпляры идентификатора deepcopy
(косвенные рекурсивные вызовы) в eagerize
.
Вам также следует удалить строки 66-144 (функция мелкого копирования, которая вам не нужна) и соответствующим образом настроить строки 1-65 (строки документации, импорт, __all__
и т. Д.).
Конечно, вы хотите отработать копию открытого текста версии copy.py
, здесь , а не аннотированную версию, на которую я ссылался (я использовал Аннотированная версия просто для того, чтобы уточнить, где именно были необходимы изменения! -).