Python 引用、浅拷贝、深拷贝解析
1、=的作用。
仅仅是地址的引用,当原列表或者新列表中任意元素改变,均会对另外一个产生影响
# 引用 # 本例中属于地址的引用,其中a和b共用同一块内存 # 当修改共用内存中的任意的内容是时,均会影响到另外的内容 a = [0, 1, 2, [3, 4]] b = a # 修改a[0]后,a[0]和b[0]都会改变 a[0] = 10 print("a:", a) print("b:", b) # 修改b[0]后,a[0]和b[0]都会改变 b[0] = 0 print("a:", a) print("b:", b) # 修改a[3][0]后,a[3][0]和b[3][0]都会改变 a[3][0] = 30 print("a:", a) print("b:", b) # 修改b[3][0]后,a[3][0]和b[3][0]都会改变 b[3][0] = 3 print("a:", a) print("b:", b) # 可以看到两个列表的内存地址相同 print("列表a的内存地址是:", id(a)) print("列表b的内存地址是:", id(b))View Code
2、使用列表的copy()方法或者copy模块的copy()方法实现拷贝
a = ["a0", "a1", "a2", ["a3", "a4"]] b = a.copy() # print("a:", a) # print("b:", b) print("a的内存地址是:", id(a)) print("b的内存地址是:", id(b))View Code
通过列表的copy()方法,可以得到一个与原列表相同的列表,当通过id()方法,查看两者的内存地址时,可以发现,两者的内存地址不同,可以当做将原列表拷贝了一份,而不是对于地址的引用。
但是,当对a列表或者b列表的前三个元素进行修改时,可以观察到仅修改了一个列表内的元素,对于另外一个列表的元素没有影响。比如
a[0] = 0 b[1] = 1 print(a) #[0, 'a1', 'a2', ['a3', 'a4']] print(b) #['a0', 1, 'a2', ['a3', 'a4']]
可以看出,修改a[0]或者b[1]时均不会修改另一个列表的对应元素。然而有例外,看下面的例子
print(a) # ['a0', 'a1', 'a2', ['a3', 'a4']] print(b) # ['a0', 'a1', 'a2', ['a3', 'a4']] a[3][0] = 3 print(a) # ['a0', 'a1', 'a2', [3, 'a4']] print(b) # ['a0', 'a1', 'a2', [3, 'a4']] b[3][1] = 4 print(a) # ['a0', 'a1', 'a2', [3, 4]] print(b) # ['a0', 'a1', 'a2', [3, 4]]
当修改a[3][0]时,b[3][0]也会跟着改变,当使用id()函数查看a[3][0]和b[3][0]时发现两者的内存地址相同,可以认为b[3][0]并不是从a那里复制了一份,而是直接指向了a[3][0]的内存地址,这样就可以解释为什么修改a列表的的列表时会影响到其他的了。
3、将所有的数据拷贝一份,需要使用copy模块的 deepcopy()方法
import copy a = ["a0", "a1", "a2", ["a3", "a4"]] b = copy.deepcopy(a)
使用deepcopy()方法实现列表的深拷贝,这种方式将原列表的元素拷贝一份,无论原列表内是否存在嵌套。
print(a) # ['a0', 'a1', 'a2', ['a3', 'a4']] print(b) # ['a0', 'a1', 'a2', ['a3', 'a4']] a[3][0] = 3 print(a) # ['a0', 'a1', 'a2', [3, 'a4']] print(b) # ['a0', 'a1', 'a2', ['a3', 'a4']] b[3][1] = 4 print(a) # ['a0', 'a1', 'a2', [3, 'a4']] print(b) # ['a0', 'a1', 'a2', ['a3', 4]]
修改内容时仅会改变自身,不会影响其他。
总结:
利用=的时候,仅仅是引用,而非拷贝,修改旧的或者新的都会影响另外一个,牵一发而动全身。
使用列表的copy方法或者使用copy模块的copy()方法,仅仅开辟一块新的内存空间,将原列表的第一层元素复制一份新的,而列表内的嵌套不会复制,仅仅是引用了内层列表的地址,属于空有其表(因为内层的无论通过新列表还是旧列表都能修改)
使用deepcoopy()方法拷贝列表,不仅开辟新空间,而且还将原列表的所有的元素都复制一份,无论原列表内是否存在嵌套的列表,属于形神具备(因为内层的列表元素不再是通过引用,而是真真正正的复制了一份新的)
PS:对于数字和字符串,赋值、浅拷贝和深拷贝的值都指向同一个内存地址。
转载于:https://www.cnblogs.com/June-King/p/10596210.html
- 点赞
- 收藏
- 分享
- 文章举报
- 解析Python中的变量、引用、拷贝和作用域的问题
- python 深入理解 赋值、引用、拷贝、作用域
- python引用,浅拷贝,深拷贝
- 04 Python正则表达式 爬虫程序 变量的引用,浅拷贝,深拷贝 多线程 进程锁 数据库模块
- Python 浅拷贝 深拷贝 及引用机制
- python 深入理解 赋值、引用、拷贝、作用域
- 深入理解 python 中的赋值、引用、拷贝、作用域
- python 引用 浅拷贝 深拷贝
- Python中 传递值 和 传递引用 的区别解析
- 【Python】Python 直接赋值、浅拷贝和深度拷贝解析
- python 引用和拷贝
- Python:创建对象中的引用和拷贝
- Python里的拷贝【引用和copy(),deepcopy()的区别】
- Python 直接赋值、浅拷贝和深度拷贝解析
- python的引用、浅拷贝与深拷贝
- Python学习笔记-对象的引用和拷贝
- 解析python中的copy 和 deepcopy深拷贝浅拷贝!
- Python语言中的引用和拷贝
- Python中的变量、引用、拷贝和作用域
- Python 浅拷贝 深拷贝 及引用机制