如何在python中复制类实例? [英] How to copy a class instance in python?

查看:103
本文介绍了如何在python中复制类实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在python中复制一个类实例.我尝试了 copy.deepcopy ,但收到错误消息:

I would like to make a copy of a class instance in python. I tried copy.deepcopy but I get the error message:

RuntimeError:目前,仅由用户(图形叶子)显式创建的变量支持Deepcopy协议

RuntimeError: Only Variables created explicitly by the user (graph leaves) support the deepcopy protocol at the moment

所以假设我有类似的东西:

So suppose I have something like:

class C(object):
    def __init__(self,a,b, **kwargs):
        self.a=a
        self.b=b
        for x, v in kwargs.items():
            setattr(self, x, v)

c = C(4,5,'r'=2)
c.a = 11
del c.b

现在我想制作 c 的相同深层副本,有没有简单的方法?

And now I want to make an identical deep copy of c, is there an easy way?

推荐答案

我基本上已经弄清楚了.我无法克服的唯一问题是,为所有类了解一组可接受的初始化参数( __ init __ 的参数).所以我必须做以下两个假设:

I have mostly figured it out. The only problem which I cannot overcome is knowing an acceptable set of initialization arguments (arguments for __init__) for all classes. So I have to make the following two assumtions:

1)我为类 C 设置了一组默认参数,我将其称为 argsC .2) C 中的所有对象都可以使用空参数初始化.

1) I have a set of default arguments for class C which I call argsC. 2) All objects in C can be initialized with empty arguments.

在这种情况下,我可以第一:从我要复制 c 的实例中初始化类 C 的新实例:

In which case I can First: Initialize a new instance of the class C from it's instance which I want to copy c:

c_copy = c.__class__(**argsC)

第二:遍历 c 的所有属性,并将属性 c_copy 设置为 c

Second: Go through all the attributes of c and set the attributes c_copy to be a copy of the attributes of c

for att in c.__dict__:
    setattr(c_copy, att, object_copy(getattr(c,att)))

其中 object_copy 是我们正在构建的函数的递归应用程序.

where object_copy is a recursive application of the function we are building.

最后:删除 c_copy 中的所有属性,但不删除 c 中的所有属性:

Last: Delete all attributes in c_copy but not in 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

因此,我们将所有内容放在一起:

So putting it all together we have:

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]}

{'a': 11, 'r': [[1], 2, 3]}

c_copy.__dict__

{'a':11,'r':[[1],2,3]}

{'a': 11, 'r': [[1], 2, 3]}

c.__dict__

{'a':11,'r':[[1,33],2,3]}

{'a': 11, 'r': [[1, 33], 2, 3]}

c_copy.__dict__

{'a':11,'r':[[1],2,3]}

{'a': 11, 'r': [[1], 2, 3]}

这是期望的结果.如果可以的话,它使用 deepcopy ,但是对于可能引发异常的情况,它可以不这样做.

Which is the desired outcome. It uses deepcopy if it can, but for the cases where it would raise an exception, it can do without.

这篇关于如何在python中复制类实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆