Clone.deepcopy () function implementation

For educational purposes only, I'm trying to implement the cloning function copy.deepcopy().

After some fun game with code and googling, I came up with the following function:

def my_deepcopy(data):

    if isinstance(data, dict):
        result = {}
        for key, value in data.items():
            result[key] = my_deepcopy(value)

        assert id(result) != id(data)

    elif isinstance(data, list):
        result = []
        for item in data:
            result.append(my_deepcopy(item))

        assert id(result) != id(data)

    elif isinstance(data, tuple):
        aux = []
        for item in data:
            aux.append(my_deepcopy(item))
        result = tuple(aux)

        assert id(result) != id(data)

    elif isinstance(data, (int, float, type(None), str, bool)):
        result = data
    else:
        raise ValueError("unexpected type")

    return result

It seems to work with all the primitive types of Python and its combinations:

# Various object types
lst_obj = [ 0, 1.1, 'foo', 'bar' ]
dict_obj = { 'zero' : 0, 'pi' : 3.1415, 'desc' : 'foobar' }
list_list_obj = [ [1,2,3], [4,5,6], [7,8,9] ]
tuple_list_obj = [ (-1,-1), (0,-1,0), (-1,0), (0,0,0,0) ]
dict_list_obj = [ {'zero' : 0}, {'pi' : 3.1415}, {'desc' : 'foobar'} ]

# Testing
my_deepcopy( lst_obj )        #OK!
my_deepcopy( dict_obj )       #OK!
my_deepcopy( list_list_obj )  #OK!
my_deepcopy( tuple_list_obj ) #OK!
my_deepcopy( dict_list_obj )  #OK!

So far, so good, but what about Arbitrary Types? How to duplicate an instance of an arbitrary object? How to detect it? Do arbitrary types have any copy constructor?

What is missing in my function for the following code to work:

class Xpto:
    pass

arbitrary = [ Xpto(), Xpto() ]
my_deepcopy( arbitrary )     #ValueError("unexpected type")
+4
source share
1 answer

" " , __dict__ :

>>> import collections
>>> isinstance([], collections.Sequence)
True
>>> isinstance((), collections.Sequence)
True
>>> isinstance('foo', collections.Sequence)
True
>>> isinstance({}, collections.Mapping)
True
>>> isinstance(23, collections.Sequence)
False
>>> isinstance(None, collections.Sequence)
False

__class__ __name__, , , if, :

def my_deepcopy(data):

    if isinstance(data, dict):
        result = {}
        for key, value in data.items():

            result[key] = my_deepcopy(value)

        assert id(result) != id(data)

    elif isinstance(data, list):
        result = []
        for item in data:
            result.append(my_deepcopy(item))

        assert id(result) != id(data)

    elif isinstance(data, tuple):
        aux = []
        for item in data:
            aux.append(my_deepcopy(item))
        result = tuple(aux)

        assert id(result) != id(data)

    elif isinstance(data, (int, float, type(None), str, bool)):
        result = data

    elif hasattr(data, '__name__'):#Its a function or a class
        auxObj = data.__class__() #Assuming it has not __init__ method defined
        auxDict = {}
        for key, value in data.__dict__:
            auxDict[key] = my_deepcopy(value)

        assert id(result) != id(data)

    else:
        raise ValueError("unexpected type")

    return result
+1

Source: https://habr.com/ru/post/1688498/


All Articles