Python3 standard library: copy copy objects

1. copy copy objects

copy module comprises two functions copy () and deepcopy (), copies of an existing object.

1.1 shallow copy

Shallow copy (shallow copy) copy () to create a new container, which is filled with references to the original content of the object. When a shallow copy of the established list of objects, will construct a new list, and appends elements of the original object to this list.

import copy
import functools

@functools.total_ordering
class MyClass:

    def __init__(self, name):
        self.name = name

    def __eq__(self, other):
        return self.name == other.name

    def __gt__(self, other):
        return self.name > other.name

a = MyClass('a')
my_list = [a]
dup = copy.copy(my_list)

print('             my_list:', my_list)
print('                 dup:', dup)
print('      dup is my_list:', (dup is my_list))
print('      dup == my_list:', (dup == my_list))
print('dup[0] is my_list[0]:', (dup[0] is my_list[0]))
print('dup[0] == my_list[0]:', (dup[0] == my_list[0]))

As a shallow copy does not copy the MyClass example, it cited dup list will point to the same my_list objects.

 

1.2 deep copy

Deep copy deepcopy () to create a new container, which is filled with a copy of the original content of the object. To create a list of deep copy constructs a new list, copy the elements of the original list, these copies will then be appended to the new list.

The previous example copy () call is replaced deepcopy (), it can be clearly seen different outputs.

import copy
import functools

@functools.total_ordering
class MyClass:

    def __init__(self, name):
        self.name = name

    def __eq__(self, other):
        return self.name == other.name

    def __gt__(self, other):
        return self.name > other.name

a = MyClass('a')
my_list = [a]
dup = copy.deepcopy(my_list)

print('             my_list:', my_list)
print('                 dup:', dup)
print('      dup is my_list:', (dup is my_list))
print('      dup == my_list:', (dup == my_list))
print('dup[0] is my_list[0]:', (dup[0] is my_list[0]))
print('dup[0] == my_list[0]:', (dup[0] == my_list[0]))

The first element of the list is no longer the same object reference, but comparing the two objects, they should be considered equal.

1.3 customize replication behavior

You can use a special method __copy __ () and __deepcopy __ () to control how a copy.

Call __copy __ () without any parameters, it will return a shallow copy of the object.

Call __deepcopy __ (), and provide a memo dictionary, which returns a deep copy of the object. All members of the attributes needed to be a deep copy of the dictionary, along with a note passed to copy.deepcopy () to control the recursion (Memo dictionary will be explained in more detail later).

import copy
import functools

@functools.total_ordering
class MyClass:

    def __init__(self, name):
        self.name = name

    def __eq__(self, other):
        return self.name == other.name

    def __gt__(self, other):
        return self.name > other.name

    def __copy__(self):
        print('__copy__()')
        return MyClass(self.name)

    def __deepcopy__(self, memo):
        print('__deepcopy__({})'.format(memo))
        return MyClass(copy.deepcopy(self.name, memo))

a = MyClass('a')

sc = copy.copy(a)
dc = copy.deepcopy(a)

Memo dictionary is used to track the value copied in order to avoid infinite recursion.

1.4 deep recursive copy

To avoid replication problems recursive data structure might bring, deepcopy () uses a dictionary to keep track of replicated objects. This dictionary will pass __deepcopy __ () method, so you can check the dictionary in the process.

import copy

class Graph:

    def __init__(self, name, connections):
        self.name = name
        self.connections = connections

    def add_connection(self, other):
        self.connections.append(other)

    def __repr__(self):
        return 'Graph(name={}, id={})'.format(
            self.name, id(self))

    def __deepcopy__(self, memo):
        print('\nCalling __deepcopy__ for {!r}'.format(self))
        if self in memo:
            existing = memo.get(self)
            print('  Already copied to {!r}'.format(existing))
            return existing
        print('  Memo dictionary:')
        if memo:
            for k, v in memo.items():
                print('    {}: {}'.format(k, v))
        else:
            print('    (empty)')
        dup = Graph(copy.deepcopy(self.name, memo), [])
        print('  Copying to new object {}'.format(dup))
        memo[self] = dup
        for c in self.connections:
            dup.add_connection(copy.deepcopy(c, memo))
        return dup

root = Graph('root', [])
a = Graph('a', [root])
b = Graph('b', [a, root])
root.add_connection(a)
root.add_connection(b)

dup = copy.deepcopy(root)

Graph class contains basic methods to FIG. May utilize a name and a list (containing the existing connected node) initiates a graph example. add_connection () method is used to establish bidirectional connections. Deep copy operator also used this method.

__deepcopy __ () method will print a message to show how this method is invoked, and needs to be managed in accordance with the contents of the memo dictionary. It is not to copy the entire list of connections, but to create a new list, then a copy of each connection is appended to this list. This ensures that the dictionary is updated memo copy each new node, while avoiding recursion or more copies of a node. The previous one, will be returned upon completion of the copied object.

Guess you like

Origin www.cnblogs.com/liuhui0308/p/12346847.html