Python之copy模块的使用

copy模块的作用

copy模块包括两个函数copy()和deepcopy(),用于复制现有的对象。
copy():是浅复制,一个新容器,其中填充原来内存对象的引用,
建立list对象的一个浅复制时,会构造一个新的list,并将原对象的元素追加到这个list。
deepcopy():是深复制,一个新容器,复制原列表的元素,然后将这些副本追加到新的列表中。

 1、浅复制

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]))
copy_shallow.py

运行效果

             my_list: [<__main__.MyClass object at 0x0000021F44E1ECC8>]
                 dup: [<__main__.MyClass object at 0x0000021F44E1ECC8>] #这里的浅复制是指把内存地址指向该对象
      dup is my_list: False
      dup == my_list: True
dup[0] is my_list[0]: True
dup[0] == my_list[0]: True

2、深复制

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]))  # 这里比较两个值是否相等
copy_deep.py

运行效果

             my_list: [<__main__.MyClass object at 0x000002022FDFED08>]
                 dup: [<__main__.MyClass object at 0x000002022FE902C8>]
      dup is my_list: False
      dup == my_list: True
dup[0] is my_list[0]: False
dup[0] == my_list[0]: True

3、自定义复制的行为

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

运行效果

__copy__()
__deepcopy__({})
<__main__.MyClass object at 0x00000205300A1408> <__main__.MyClass object at 0x00000205300A1348>

4、深复制中的递归,为了避免复制递归数据结构可能带来的问题,deepcopy()使用了一个字典来跟踪已复制的对象。将这个字典传入__deepcopy__()方法,这样在该方法中也可以检查这个字典。

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

 

 运行效果

Calling __deepcopy__ for Graph(name=root, id=2396903141256)
  Memo dictionary:
    (empty)
  Copying to new object Graph(name=root, id=2396902987016)

Calling __deepcopy__ for Graph(name=a, id=2396903141192)
  Memo dictionary:
    Graph(name=root, id=2396903141256): Graph(name=root, id=2396902987016)
  Copying to new object Graph(name=a, id=2396902989320)

Calling __deepcopy__ for Graph(name=root, id=2396903141256)
  Already copied to Graph(name=root, id=2396902987016)

Calling __deepcopy__ for Graph(name=b, id=2396903141128)
  Memo dictionary:
    Graph(name=root, id=2396903141256): Graph(name=root, id=2396902987016)
    Graph(name=a, id=2396903141192): Graph(name=a, id=2396902989320)
    2396903141256: Graph(name=root, id=2396902987016)
    2396903146184: [Graph(name=root, id=2396903141256), Graph(name=a, id=2396903141192)]
    2396903141192: Graph(name=a, id=2396902989320)
  Copying to new object Graph(name=b, id=2396902987208)
posted @ 2020-06-30 11:38  小粉优化大师  阅读(486)  评论(0编辑  收藏  举报