Python中浅拷贝,深拷贝的区别

Python中浅拷贝,深拷贝的区别

以列表为例, 三者的区别主要在新列表中元素跟原来列表中元素是否仍有联系

	1, 对元组类型来说,使用 tuple() 或者切片操作符':',它会返回一个指向相同元组的引用, 内存地址的引用计数会加1, 
	但copy前后的对象指向的是同一块内存地址, 也就不会有区别了.
	2. 浅拷贝, 原列表中可变元素的操作会影响新列表中元素
		以列表为例, 首先会初始化一块新的内存地址, 这里存的是原列表的地址, 
		新的列表指向的是新内存地址, 这跟原列表的地址是不一样的
		副作用, copy前的对象影响新的对象
			l1 = [[1, 2], (30, 40)]
			l2 = list(l1)
			l1.append(100)
			l1[0].append(3)
			l1 		#[[1, 2, 3], (30, 40), 100]
			l2 		#[[1, 2, 3], (30, 40)]
	3. 深拷贝, 原列表元素完全不会影响新列表中元素
		初始化一块新的内存地址, 新的列表指向这一块新的内存地址, 
		然后会将原列表里元素的值拷贝到新的内存中, 完全不会受到原列表的影响

浅拷贝

  1. 下面四种形式是等价的
    new_list = old_list.copy()
    new_list = old_list[:]
    new_list = list(old_list)
    new_list = copy.copy(old_list)
  2. 上面四种形式得到的结果是一致的,对简单类型元素按值赋值,符合类型元素复制其地址
    import copy \n new_list = copy.copy(old_list)比list.copy()慢一点,
    区别在于copy模块需要先确定old_list是列表类型
  3. 因为在复制完成后修改a中第一个元素的值, b中元素值没有改变
    所以b有自己的内存,简单类型的元素’foo’是在b的新分配的内存区域中, 不同于a中’foo’的内存地址
    因为在复制完成后修改a中类实例的属性, b中类属性也改变了
    所以我们得到: b的复合类型对象Foo类实例foo指向a中foo实例的地址

深拷贝

  1. 形式 new_list = copy.deepcopy(old_list)
  2. 对简单类型元素按值赋值,符合类型元素递归的复制其值到新列表中
  3. 因为在复制完成后修改a中类实例的属性, b中类实例的属性没有改变
    所以我们得到: b的复合类型对象Foo类实例不同于a中foo实例的地址

参考

  1. Shallow and deep copy operations
  2. how-to-clone-or-copy-a-list

Code

import copy
class Foo(object):
    def __init__(self, val):
        self.val = val
    def __repr__(self):
        return str(self.val)
foo = Foo(1)
a = ['foo', foo]
# ae只是a的别名, ae自己没有独立的内存,仍然使用a的内存, 二者的内存地址是一样的
ae = a
# 因为在复制完成后修改a中第一个元素的值, b中元素值没有改变
# 所以b有自己的内存,简单类型的元素'foo'是在b的新分配的内存区域中, 不同于a中'foo'的内存地址
# 因为在复制完成后修改a中类实例的属性, b中类属性也改变了
# 所以我们得到: b的复合类型对象Foo类实例foo指向a中foo实例的地址
b = a.copy() 
c = a[:]
d = list(a)
e = copy.copy(a)
# 因为在复制完成后修改a中类实例的属性, b中类实例的属性没有改变
# 所以我们得到: b的复合类型对象Foo类实例不同于a中foo实例的地址
f = copy.deepcopy(a)

# edit orignal list and instance
a.append('baz')
a[0] = 'foo modified'
foo.val = 5

print(' original: %r\n equal: %r\n list.copy(): %r\n slice: %r\n list(): %r\n copy: %r\n deepcopy: %r'
      % (a, ae, b, c, d, e, f))
'''
 original: ['foo modified', 5, 'baz']
 equal: ['foo modified', 5, 'baz']
 list.copy(): ['foo', 5]
 slice: ['foo', 5]
 list(): ['foo', 5]
 copy: ['foo', 5]
 deepcopy: ['foo', 1]
''' 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值