python的深浅拷贝原理 python值传递和引用传递

python的深浅拷贝原理 python值传递和引用传递,第1张

概述一、变量存储变量的存储分为栈区和堆区,两者之间是引用关系,变量名放在栈区内存,真实的数据存放在堆内存里栈区通过指针来指向对应的堆区内存  二、直接赋值链式赋值是直接引用栈区变量名,相当于一个人起两个名字,表示的还是一毛一样的一个对象l=[1,2,[1,2]]l1=lprint( 一、变量存储

变量的存储分为栈区和堆区,两者之间是引用关系,变量名放在栈区内存,真实的数据存放在堆内存里

栈区通过指针来指向对应的堆区内存

@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值传递和引用传递所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1184838.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存