How to copy a class instance in python?

前端 未结 3 1510
遥遥无期
遥遥无期 2021-02-07 03:16

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

RuntimeError: Only Variables cr

相关标签:
3条回答
  • 2021-02-07 03:40

    Yes you can make a copy of class instance using deepcopy:

    from copy import deepcopy
    
    c = C(4,5,'r'=2)
    d = deepcopy(c)
    

    This creates the copy of class instance 'c' in 'd' .

    0 讨论(0)
  • 2021-02-07 03:58

    One way to do that is by implementing __copy__ in the C Class like so:

    class A:
        def __init__(self):
            self.var1 = 1
            self.var2 = 2
            self.var3 = 3
    
    class C(A):
        def __init__(self, a=None, b=None, **kwargs):
            super().__init__()
            self.a = a
            self.b = b
            for x, v in kwargs.items():
                setattr(self, x, v)
    
        def __copy__(self):
            self.normalizeArgs()
            return C(self.a, self.b, kwargs=self.kwargs)
    
        # THIS IS AN ADDITIONAL GATE-KEEPING METHOD TO ENSURE 
        # THAT EVEN WHEN PROPERTIES ARE DELETED, CLONED OBJECTS
        # STILL GETS DEFAULT VALUES (NONE, IN THIS CASE)
        def normalizeArgs(self):
            if not hasattr(self, "a"):
                self.a      = None
            if not hasattr(self, "b"):
                self.b      = None
            if not hasattr(self, "kwargs"):
                self.kwargs = {}
    
    cMain   = C(a=4, b=5, kwargs={'r':2})
    
    del cMain.b
    cClone  = cMain.__copy__()
    
    cMain.a = 11
    
    del  cClone.b
    cClone2 = cClone.__copy__()
    
    print(vars(cMain))
    print(vars(cClone))
    print(vars(cClone2))
    

    0 讨论(0)
  • 2021-02-07 03:59

    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) 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.

    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)
    

    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)))
    

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

    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)
    

    Putting this all together we have:

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

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

    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.

    0 讨论(0)
提交回复
热议问题