变量的存储分为栈区和堆区,两者之间是引用关系,变量名放在栈区内存,真实的数据存放在堆内存里
栈区通过指针来指向对应的堆区内存
@H_403_7@
二、直接赋值
链式赋值是直接引用栈区变量名,相当于一个人起两个名字,表示的还是一毛一样的一个对象
l = [1,2,[1,2]]l1 = lprint(ID(l),ID(l1)) #43418120 43418120 两个列表一样
三、浅拷贝
浅拷贝只复制指向堆区的指针,而不复制对象本身,新旧对象还是共享同一块内存
对于不可变类型指向的是真实数据,对于可变类型指向的是该对象的栈区
改变真身内不可变类型,本质是真身重新申请内存改变自己的指针,不改变原内存,不影响拷贝的指针指向,拷贝的相应元素保持不变
改变真身内可变类型,拷贝的相应元素跟着变化
@H_403_7@
import copyl = [1,2,[1,2]]l1 = copy.copy(l) # 拷贝一份 print(ID(l),ID(l1)) #656 936 浅拷贝来的不是原来的对象,而是创建了一个新对象print(ID(l[0]),ID(l[1]),ID(l[2]),) #224 256 928 print(ID(l1[0]),ID(l1[1]),ID(l1[2]),) #224 256 928 浅拷贝和原来指向的是同一块内存l[0] = 222print(l,l1) #[222, 2, [1, 2]] [1, 2, [1, 2]]print(ID(l[0]),ID(l[1]),ID(l[2]),) #296 256 928 改变不可变类型的值是重新在堆区申请了一块内存,ID改变print(ID(l1[0]),ID(l1[1]),ID(l1[2]),) #224 256 928 l[2].append(666)print(l,l1) #[222, 2, [1, 2, 666]] [1, 2, [1, 2, 666]]print(ID(l[0]),ID(l[1]),ID(l[2]),) #296 256 928 改变可变类型其ID不变(可变类型是堆区里面又套栈区,改变对于列表本身类似于链式赋值,起别名,你细品)print(ID(l1[0]),ID(l1[1]),ID(l1[2]),) #224 256 928四、深拷贝
不管是可变还是不可变类型,统统指向真实的数据,所以不管真身怎么变,拷贝来的都不变
拷贝出来ID是不一样的,但是有个别时候会违背常理出现ID一样,这是小整数池造成的
@H_403_7@
import copyl = [1,2,[1,2]]l1 = copy.deepcopy(l) # 拷贝一份print(ID(l),ID(l1)) #656 936 深拷贝来的也不是原来的对象,而是创建了一个新对象print(ID(l[0]),ID(l[1]),ID(l[2]),ID(l[2][0]),ID(l[2][1]),) #224 256 296 224 256 print(ID(l1[0]),ID(l1[1]),ID(l1[2]),ID(l1[2][0]),ID(l1[2][1]),) #224 256 632 224 256五、值传递和引用传递
python基本的参数传递机制有两种:值传递和引用传递
值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何 *** 作都是作为局部变量进行,不会影响主调函数的实参变量的值。
引用传递(pass-by-reference)过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何 *** 作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何 *** 作都影响了主调函数中的实参变量
不可变参数是值类型,值传递:数字,字符串,元组
可变参数,引用传递,传过去后可以被修改内存,如:列表,字典
@H_403_7@
@H_403_7@
@H_403_7@
ps:对于不可变类型尤其注意坑点:
task = {'test':'就TM离谱'}waiting_recog = {}recoging_tasks = {}task['num_recoging'] = 0for i in range(2): num = i waiting_recog[num] = task task['num_recoging'] += 1recoging_tasks['task_ID'] = taskprint(waiting_recog)print(recoging_tasks)"""{0: {'test': '就TM离谱', 'num_recoging': 2}, 1: {'test': '就TM离谱', 'num_recoging': 2}}{'task_ID': {'test': '就TM离谱', 'num_recoging': 2}}"""总结
以上是内存溢出为你收集整理的python的深浅拷贝原理 python值传递和引用传递全部内容,希望文章能够帮你解决python的深浅拷贝原理 python值传递和引用传递所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)