Я в основном разобрался. Единственная проблема, которую я не могу преодолеть, - это знание приемлемого набора аргументов инициализации (аргументов для __init__
) для всех классов. Поэтому я должен сделать следующие два предположения:
1) У меня есть набор аргументов по умолчанию для класса C
, который я называю argsC
. 2) Все объекты в C
могут быть инициализированы пустыми аргументами.
В этом случае я могу Сначала: инициализировать новый экземпляр класса C
из этого экземпляра, который я хочу скопировать c
:
c_copy = c.__class__(**argsC)
Второй. Просмотрите все атрибуты c
и установите атрибуты c_copy
как копии атрибутов c
for att in c.__dict__:
setattr(c_copy, att, object_copy(getattr(c,att)))
где object_copy
- рекурсивное приложение создаваемой нами функции.
Последнее: удалите все атрибуты в c_copy
, но не в c
:
for att in c_copy.__dict__:
if not hasattr(c, att):
delattr(c_copy, att)
Собирая все это вместе, мы получаем:
import copy
def object_copy(instance, init_args=None):
if init_args:
new_obj = instance.__class__(**init_args)
else:
new_obj = instance.__class__()
if hasattr(instance, '__dict__'):
for k in instance.__dict__ :
try:
attr_copy = copy.deepcopy(getattr(instance, k))
except Exception as e:
attr_copy = object_copy(getattr(instance, k))
setattr(new_obj, k, attr_copy)
new_attrs = list(new_obj.__dict__.keys())
for k in new_attrs:
if not hasattr(instance, k):
delattr(new_obj, k)
return new_obj
else:
return instance
Итак, сложив все это вместе, мы имеем:
argsC = {'a':1, 'b':1}
c = C(4,5,r=[[1],2,3])
c.a = 11
del c.b
c_copy = object_copy(c, argsC)
c.__dict__
{'a': 11, 'r': [[1], 2, 3]}
c_copy.__dict__
{'a': 11, 'r': [[1], 2, 3]}
c.__dict__
{'a': 11, 'r': [[1, 33], 2, 3]}
c_copy.__dict__
{'a': 11, 'r': [[1], 2, 3]}
Что и есть желаемый результат. Он использует deepcopy
, если может, но в тех случаях, когда он вызывает исключение, он может обойтись и без него.
person
patapouf_ai
schedule
30.01.2018
__copy__
dunder. Или__deepcopy__
, в зависимости от того, что вам нужно. - person cs95   schedule 19.01.2018copy.deepcopy
. так что простоc2 = copy.deepcopy(c)
, затемvars(c2) == {'a': 11, 'r': 2}
иvars(c) == {'a': 11, 'r': 2}
, но трассировка, о которой вы сообщаете, не будет производиться указанным вами определением класса ... - person juanpa.arrivillaga   schedule 19.01.2018copy
будет обрабатывать типы, которые не определяют__copy__
или__deepcopy__
. Я не думаю, что это связано с этим связанным дубликатом, сообщение об ошибке предполагает, что глубокая копия была намеренно переопределена, чтобы вызвать ошибку времени выполнения. - person juanpa.arrivillaga   schedule 19.01.2018torch.nn.Module
, но это немного сложно, поэтому я привожу здесь более простой пример. Просто констатирую, что в моем случаеdeepcopy
не работает, поэтому мне нужно другое решение. - person patapouf_ai   schedule 19.01.2018