程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python3 tutorial: detailed usage of copy module

編輯:Python

copy- Object copy module ; It provides the function of shallow copy and deep copy to copy objects , Corresponding to the two functions in the module respectively copy() and deepcopy().

1. Shallow copy (Shallow Copies)

copy() Created Shallow copy Is a new container , It contains references to the contents of the original object . That is, only the parent object is copied , Does not copy the inner child of an object . That is, shallow copy only copies the object itself , The object referenced by this object is not copied . such as , When creating a shallow copy of a list object , A new list will be constructed , And add the elements of the original object to it .

import copy
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]))
my_list: [<__main__.MyClass object at 0x0000026DFF98D128>]
dup: [<__main__.MyClass object at 0x0000026DFF98D128>]
dup is my_list: False
dup == my_list: True
dup[0] is my_list[0]: True
dup[0] == my_list[0]: True

In the shallow copy example above ,dup By my_list Copy it , however MyClass Instances will not be copied , therefore dup List and my_list The same object is referenced in .

2. Deep copy (Deep Copies)

deepcopy() Created Deep copy Is a new container , It contains a copy of the contents of the original object . Deep copy completely copies the parent object and its children . That is, create a new composite object , Copy all child objects recursively at the same time , The new composite object has no association with the original object . Although immutable child objects are actually shared , But it does not affect their mutual independence .

Replace the above code with deepcopy(), You will find the difference :

import copy
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]))
my_list: [<__main__.MyClass object at 0x000002442E47D128>]
dup: [<__main__.MyClass object at 0x00000244352EF208>]
dup is my_list: False
dup == my_list: True
dup[0] is my_list[0]: False
dup[0] == my_list[0]: True

In the list MyClass The instance is no longer the same object reference , But a new copy , But when two objects are compared , Their values are still equal .

3. Custom copy behavior

You can customize __copy__() and __deepcopy__() Method to change the default copy behavior .

__copy()__ Is a parameterless method , It returns a shallow copy object ;

__deepcopy()__ Accept a note (memo) Dictionary parameters , Returns a deep copy object . All member attributes that require deep copy should be passed to copy.deepcopy() , as well as memo Dictionaries , To control recursion .( The following example will explain memo Dictionaries ).

The following example demonstrates how to call these methods :

import copy
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)
__copy__()
__deepcopy__({
})

memo Dictionaries are used to track values that have been copied , To avoid infinite recursion .

4. Recursion in deep copy

To avoid the problem of recursive data structure when copying , deepcopy() Use a dictionary to keep track of objects that have been copied . This dictionary is passed on to deepcopy() Method to check .

The following example shows an interrelated data structure ( Directed graph ), How to realize __deepcopy__() Method to prevent recursion .

''' No one answers the problems encountered in learning ? Xiaobian created a Python Exchange of learning QQ Group :711312441 Looking for small partners who share the same aspiration , Help each other , There are also good video tutorials and PDF e-book ! '''
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 includes some basic directed graph methods . You can initialize an instance with a name and a list of existing nodes to which it is connected . add_connection() Method to set up a two-way connection . It is also used by the deep copy operator .

__deepcopy__() Method prints its call information , And manage as needed memo Dictionary content . It does not copy the entire connection list , Instead, create a new list , And add a copy of a single connection . Ensure that each new node is updated as it is replicated memo Dictionaries , And avoid copying nodes recursively or repeatedly . Same as before , This method returns the copied object on completion .

Calling __deepcopy__ for Graph(name=root, id=2115579269360)
Memo dictionary:
(empty)
Copying to new object Graph(name=root, id=2115695211072)
Calling __deepcopy__ for Graph(name=a, id=2115695210904)
Memo dictionary:
Graph(name=root, id=2115579269360): Graph(name=root, id=2115695211072)
Copying to new object Graph(name=a, id=2115695211184)
Calling __deepcopy__ for Graph(name=root, id=2115579269360)
Already copied to Graph(name=root, id=2115695211072)
Calling __deepcopy__ for Graph(name=b, id=2115695210960)
Memo dictionary:
Graph(name=root, id=2115579269360): Graph(name=root, id=2115695211072)
Graph(name=a, id=2115695210904): Graph(name=a, id=2115695211184)
2115579269360: Graph(name=root, id=2115695211072)
2115695219408: [Graph(name=root, id=2115579269360), Graph(name=a, id=2115695210904)]
2115695210904: Graph(name=a, id=2115695211184)
Copying to new object Graph(name=b, id=2115695211240)

The second time you encounter the root node , If a node has been copied , __deepcopy__() Detect recursion , And from memo Reuse existing values in the dictionary , Instead of creating a new object .


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved