python中赋值、浅拷贝、深拷贝

Python中的赋值、浅拷贝和深拷贝:

赋值:


在python中, 对象的赋值就是简单的对象引用, 这点和C++不同, 如下所示: 
a = [1,2,"hello",['python', 'C++']] 
b = a
在上述情况下, a和b是一样的, 他们指向同一片内存, b不过是a的别名, 是引用。
我们可以使用b is a 去判断, 返回True, 表明他们地址相同, 内容相同, 也可以使用id()函数来查看两个列表的地址是否相同。
赋值操作(包括对象作为参数、 返回值)不会开辟新的内存空间, 它只是复制了对象的引用。
也就是说除了b这个名字之外, 没有其他的内存开销。
修改了a, 也就影响了b;同理, 修改了b, 也就影响了a


浅拷贝(shallow coopy):


浅拷贝会创建新对象, 其内容是原对象的引用。
浅拷贝有三种形式:切片操作、 工厂函数、 copy模块中的copy函数
比如上述的列表a
切片操作: b = a[:] 或者 b = [x for x in a]
工厂函数: b = list(a)
copy函数: b = copy.copy(a)
浅拷贝产生的列表b不再是列表a了, 使用is判断可以发现他们不是同一个对象, 使用id查看, 他们也不指向同一片内存空间。
但是当我们使用id(x) for x in a 和 id(x) for x in b来查看a和b中元素的地址时, 可以看到二者包含的元素的地址是相同的。
在这种情况下, 列表a和b是不同的对象, 修改列表b理论上不会影响到列表a。
但是要注意的是, 浅拷贝之所以称之为浅拷贝, 是它仅仅只拷贝了一层, 在列表a中有一个嵌套的list, 如果我们修改了它, 情况就不一样了。
比如: a[3].append('java')。 查看列表b, 会发现列表b也发生了变化, 这是因为, 我们修改了嵌套的list, 修改外层元素, 会修改它的引用, 让它们指向别的位置, 修改嵌套列表中的元素, 列表的地址并未发生变化,指向的都是用一个位置。


深拷贝(Deep copy):


深拷贝只有一种形式, copy模块中的deepcopy()函数
深拷贝和浅拷贝对应, 深拷贝拷贝了对象的所有元素, 包括多层嵌套的元素。 因此, 它的时间和空间开销要高。
同样的对列表a, 如果使用 b = copy.deepcopy(a), 再修改列表b将不会影响到列表a, 即使嵌套的列表具有
更深的层次, 也不会产生任何影响, 因为深拷贝拷贝出来的对象根本就是一个全新的对象, 不再与原来的对象有任何的关联。

拷贝的注意点:

对于非容器类型, 如数字、 字符, 以及其他的“原子”类型, 没有拷贝一说, 产生的都是原对象的引用。
如果元组变量值包含原子类型对象, 即使采用了深拷贝, 也只能得到浅拷贝。

猜你喜欢

转载自blog.csdn.net/qq_35169931/article/details/85869938