python学习---浅拷贝与深拷贝的关键点
1. python 可变与不可变对象
可变对象:指向地址不变,内容改变(原指向内存地址修改内容)
不可变对象:指向地址改变,内容改变(原指向地址不能改,重新开辟新的内存地址保持,所以地址与内容都发生改变)
- 可变对象:list dict set
- 不可变对象:tuple string int float bool
2. 浅拷贝与深拷贝
第一个注意点:
- 对于不可变对象来说,赋值操作其实就可以满足上面说的实际应用场景
- 所以!后面要讲的浅拷贝、深拷贝对于不可变对象来说,和赋值操作是一样的效果!
- 记住!浅拷贝、深拷贝只针对可变对象,即列表、集合、字典!
3.浅拷贝: copy
一句话概括:浅拷贝会创建一个新对象,该新对象存储原始元素的引用,指向的对象并不是同一个
- 浅拷贝后的值是相同的
- 浅拷贝后的会产生一个新的对象
3.1.修改列表内的可变元素
import copy old = [[1, 2], [3, 4]] new = copy.copy(old) print("old list", id(old)) old.append([5, 6]) old[1][1] = 44 print("Old list:", old, "id is :", id(old)) print("New list:", new, "id is :", id(new)) 运行结果: old list 21217408 Old list: [[1, 2], [3, 44], [5, 6]] id is : 21217408 New list: [[1, 2], [3, 44]] id is : 21218128
浅拷贝会开辟新的内存地址,新的变量会指向新内存地址
列表里面的元素(可变元素)地址则指向同一个内存地址,修改旧的列表元素,则两个都发生改变
3.2 修改列表内的不可变对象元素
import copy old = [1, 2, "string", (1, 2,)] new = copy.copy(old) print("old list", id(old)) old.append([5, 6]) old[1] += 22 old[2] += "s" old[3] += (44,) print("Old list:", old, "id is :", id(old),id(old[3])) print("New list:", new, "id is :", id(new),id(new[3])) 运行结果: old list 30941232 Old list: [1, 24, 'strings', (1, 2, 44), [5, 6]] id is : 30941232 30884088 New list: [1, 2, 'string', (1, 2)] id is : 30887848 29210144
对于不可变对象,列表对象与列表里面的元素都不会指向相同的地址
4. 深拷贝:deepcopy
- 创建一个新对象,且存储的对象引用也是新的
- 深,意味着会把所有子元素对象也复制生成一个新对象
import copy old = [[1, 2], [3, 4]] new = copy.deepcopy(old) print("old list", id(old)) old.append([5, 6]) print("Old list:", old, "id is :", id(old),id(old[1])) print("New list:", new, "id is :", id(new),id(new[1])) 运行结果: old list 27705512 Old list: [[1, 2], [3, 4], [5, 6]] id is : 27705512 27667512 New list: [[1, 2], [3, 4]] id is : 27706232 27705872
- 两个变量保存了不同的对象引用
- 可变对象元素(子对象)的内存地址也是不同的
参考文章:https://www.cnblogs.com/poloyy/p/15084277.html