2012-01-14 7 views
4

ли Возможное только глубоко скопировать определенные типы объектов, например, в виде списка, Словаре или кортежPython DeepCopy .. вид

Пример: [[1, <SomeObj>], <OtherObj>]

Я хочу глубокой копии первый список (и, конечно, 1), но не SomeObj или OtherObj. Те должны оставаться в качестве рефери.

Это можно сделать с помощью некоторой функции, что я не знаком с ней или я должен написать свою собственную функцию? ...

ответ

3

Насколько я знаю, для этого нет никакой полезности. Встроенные модули copy и deepcopy требуют, чтобы объекты предоставляли свои методы __copy__ и __deepcopy__ для переопределения поведения по умолчанию. Это нехорошая идея ИМХО, так как вы не всегда хотите получить копии того же рода ...

Написание функции для этого не должно быть затруднительным. Вот пример, который работает для списков, кортежей и dicts:

def mycopy(obj): 
    if isinstance(obj, list): 
     return [mycopy(i) for i in obj] 
    if isinstance(obj, tuple): 
     return tuple(mycopy(i) for i in obj) 
    if isinstance(obj, dict): 
     return dict(mycopy(i) for i in obj.iteritems()) 
    return obj 
+2

Для больших вещей, это было бы более эффективным путем удаления '[' и ']' в кортеже отрасли и ' ['и'] 'и сменив' .items() 'на' .iteritems() 'в ветке dict. Эти изменения также являются питоническими по стилю. –

+0

@ChrisMorgan ответ обновлен. Спасибо за советы, я не знал этих форм. – mgibsonbr

+2

Если вы не знакомы с ними, посмотрите (a) выражения генератора (это то, что вы получаете, когда вы вынимаете '[' и ']', в противном случае это понимание списка) и (b) итераторы (' dict.items() 'создает список,' dict.iteritems() 'создает итератор, для получения дополнительной информации обратитесь к документации' dict'. –

1

Я не знаю ни одного питона инструмент, который будет DeepCopy только основные типы и сохранить другие элементы в качестве ссылок.

Я думаю, что вы должны написать небольшую рекурсивную функцию для этого (до 20 строк).

4

Вы можете сделать это с copy.deepcopy довольно легко перекрывая метод __deepcopy__ в каждом из классов, вам нужно это в случае, если вы хотите различное копирование поведение в зависимости от того. ситуация, вы можете просто установить функцию __deepcopy__ во время выполнения, а затем сбросить его:

import copy 
class OtherObject(object): 
    pass 

l = [[1, 2, 3], [4, 5, 6], OtherObject()] 
# first, save the old deepcopy if there is one 
old_deepcopy = None 
if hasattr(OtherObject, __deepcopy__): 
    old_deepcopy = OtherObject.__deepcopy__ 

# do a shallow copy instead of deepcopy 
OtherObject.__deepcopy__ = lambda self, memo: self 
l2 = copy.deepcopy(l) 
# and now you can replace the original behavior 
if old_deepcopy is not None: 
    OtherObject.__deepcopy__ = old_deepcopy 
else: 
    del OtherObject.__deepcopy__ 

>>> l[0] is l2[0] 
False 
>>> l[1] is l2[1] 
False 
>>> l[2] is l2[2] 
True 
Смежные вопросы