个人理解原型模式就是对象的拷贝,在创建一个新的对象的成本相对较高的时候,可以以一个现成对象为范本,复制出一个对象。python 为对象的拷贝提供了一个标准模块 copy,我觉得就没必要生搬硬套地按照对象关系写什么原型模式了,直接用吧。代码示例如下:
#!/usr/bin/env python #coding: utf-8 from copy import copy class Proto: def __init__(self, a, b): self._a = a self._b = b if __name__ == '__main__': p = Proto(1, 2) pc = copy(p) print(pc.__dict__, p.__dict__)输出:
{'_a': 1, '_b': 2} {'_a': 1, '_b': 2}copy是浅拷贝函数,在上面例子中使用是正确的;但是,当属性是引用类型,我们想拷贝出一个完全独立的新对象,使用copy就会有问题,如下代码:
#!/usr/bin/env python #coding: utf-8 from copy import copy class Proto: def __init__(self, a, b, c): self._a = a self._b = b self._c = c if __name__ == '__main__': p = Proto(1, 2, [1,2]) pc = copy(p) pc._c[1] = 100 print(pc.__dict__, p.__dict__)输出
{'_a': 1, '_b': 2, '_c': [1, 100]} {'_a': 1, '_b': 2, '_c': [1, 100]}此时,我们应该使用 deepcopy 深拷贝,代码如下:
#!/usr/bin/env python #coding: utf-8 from copy import deepcopy class Proto: def __init__(self, a, b, c): self._a = a self._b = b self._c = c if __name__ == '__main__': p = Proto(1, 2, [1,2]) pc = deepcopy(p) pc._c[1] = 100 print(pc.__dict__, p.__dict__)输出:
{'_a': 1, '_b': 2, '_c': [1, 100]} {'_a': 1, '_b': 2, '_c': [1, 2]}deepcopy会递归地把所有引用类型展开,不管嵌套多少层,我们可以多嵌套基层列表看下效果:
#!/usr/bin/env python #coding: utf-8 from copy import copy, deepcopy class Proto: def __init__(self, a, b, c): self._a = a self._b = b self._c = c if __name__ == '__main__': p = Proto(1, 2, [1,2, [3,4, [5,6]]]) pc = deepcopy(p) pc._c[2][2][0] = 99 print(pc.__dict__, p.__dict__)输出:
{'_a': 1, '_b': 2, '_c': [1, 2, [3, 4, [99, 6]]]} {'_a': 1, '_b': 2, '_c': [1, 2, [3, 4, [5, 6]]]}