zoukankan      html  css  js  c++  java
  • python变量、引用、拷贝之间的关系

    Python中一切皆为对象,不管是集合变量还是数值型or字符串型的变量都是一个引用,都指向对应内存空间中的对象。

    简而言之:
    变量直接赋值:新变量本身及其内部的元素都与原变量指向相同的内存空间,并且值相同,当一个发生变化时,另一个也随之变化。
    变量浅拷贝:新变量本身与原变量指向不同的内存空间,但是新变量内部的元素与原变量指向相同的内存空间;当改变原变量内部的可变对象的值时,新变量内部的值也发生随之变化;改变原变量内部的不可变对象的值时,新变量内部的值不随之变化;反之亦然(即改变新变量时)。
    变量深拷贝:新变量与原变量本身及其内部元素都指向不同的内存空间,改变原变量的值时,新变量中的值不会发生变化,反之亦然。
     
    1. 不可变对象:int,float,long,str,tuple等;
     
     1 In[20]: a = 1  
     2 In[21]: b = a  
     3 In[22]: id(a)  
     4 Out[22]: 33719592L  
     5 In[23]: id(b)  
     6 Out[23]: 33719592L  
     7 In[24]: a = 2  
     8 In[25]: id(a)  
     9 Out[25]: 33719568L  
    10 In[26]: id(b)  
    11 Out[26]: 33719592L  
    12 In[27]: b = 3  
    13 In[28]: id(b)  
    14 Out[28]: 33719544L 
     
    可以看出最开始a、b指向同一个内存空间,但是当改变a的值时,a指向了新的内存空间(此时b没有发生变化),改变b时b也指向了新的内存空间;类似于C语言中的值传递。
     
    2. 可变对象:list,set,dict, array, matrix等
     
     1 In[29]: list1 = [1,2,3]  
     2 In[30]: list2 = list1  
     3 In[31]: id(list1)  
     4 Out[31]: 61244552L  
     5 In[32]: id(list2)  
     6 Out[32]: 61244552L  
     7 In[33]: list1[0] = 101  
     8 In[34]: id(list1)  
     9 Out[34]: 61244552L  
    10 In[35]: id(list2)  
    11 Out[35]: 61244552L  
    12 In[36]: list1  
    13 Out[36]: [101, 2, 3]  
    14 In[37]: list2  
    15 Out[37]: [101, 2, 3]  
    16 In[38]: list2[1] = 102  
    17 In[39]: id(list1)  
    18 Out[39]: 61244552L  
    19 In[40]: id(list2)  
    20 Out[40]: 61244552L  
    21 In[41]: list1  
    22 Out[41]: [101, 102, 3]  
    23 In[42]: list2  
    24 Out[42]: [101, 102, 3]  

    刚开始list1和list2指向同一个内存空间,改变list1中的值时,list2也跟着改变,但是它们指向的内存空间没有发生变化;同样,改变list2中的值时,list1的值也跟着变化,它们仍然指向同一个内存空间。

    浅拷贝和深拷贝:

    下述例子中:b和a指向同一个内存空间,改变a中的值,则b跟着改变。c是a浅拷贝,c指向和a不同的内存空间,但是如果a中有一个元素为可变对象,则c中的此元素和a中的元素指向同一个内存空间,则改变a中此可变对象里面的值时,c中的值也改变;改变a中不可变对象的元素的值时,c中的值不发生变化。d是a的深拷贝,d和a指向不同的内存空间,d内部的元素和a内部元素也指向不同的空间,改变a里面的值时,d不会发生变化。

    例子说明:

     1 import copy  
     2 a = [1,[1, 2, 3], [4, 5, 6]]  
     3 b = a  
     4 c = copy.copy(a)  
     5 d = copy.deepcopy(a)    
     7 a.append(15)  
     8 a[1][2] = 10  
     9 a[0] = 0     
    11 print a  
    12 print b  
    13 print c  
    14 print d     
    16 print id(a)  
    17 print id(b)  
    18 print id(c)  
    19 print id(d)

    输出
    1 [0, [1, 2, 10], [4, 5, 6]]  
    2 [0, [1, 2, 10], [4, 5, 6]]  
    3 [1, [1, 2, 10], [4, 5, 6]]  
    4 [1, [1, 2, 3], [4, 5, 6]]  
    5 38023496  
    6 38023496  
    7 36700104  
    8 38023368 

    再如
    1 print 'a[1]',id(a[1])  
    2 print 'b[1]',id(b[1])  
    3 print 'c[1]',id(c[1])  
    4 print 'd[1]',id(d[1]),'
    '  
    6 print 'a[0]',id(a[0])  
    7 print 'b[0]',id(b[0])  
    8 print 'c[0]',id(c[0])  
    9 print 'd[0]',id(d[0])

    输出
    1 a[1] 39654856  
    2 b[1] 39654856  
    3 c[1] 39654856  
    4 d[1] 39704904     
    6 a[0] 34112864  
    7 b[0] 34112864  
    8 c[0] 34112834  
    9 d[0] 34112840 
    简而言之:
    变量直接赋值:新变量本身及其内部的元素都与原变量指向相同的内存空间,并且值相同,当一个发生变化时,另一个也随之变化。
    变量浅拷贝:新变量本身与原变量指向不同的内存空间,但是新变量内部的元素与原变量指向相同的内存空间;当改变原变量内部的可变对象的值时,新变量内部的值也发生随之变化;改变原变量内部的不可变对象的值时,新变量内部的值不随之变化;反之亦然(即改变新变量时)。
    变量深拷贝:新变量与原变量本身及其内部元素都指向不同的内存空间,改变原变量的值时,新变量中的值不会发生变化,反之亦然。
     
     
     
    参考:http://blog.csdn.net/u013573813/article/details/53349798
  • 相关阅读:
    80X86常用汇编指令集(不断补充完善中)
    重温大师经典:Martin Fowler 的持续集成
    .NET Framework 将有限地向开发者公开源代码
    DotNet源代码中的模式Builder生成器模式
    Delphi内嵌汇编语言BASM精要(转帖)
    sealed关键字用法
    VS2008设置查看.NET源码的方法
    基于LINQ to SQL的WEB开发三层架构(1)
    拓扑排序
    HDU1495 非常可乐(BFS)
  • 原文地址:https://www.cnblogs.com/wt869054461/p/6831114.html
Copyright © 2011-2022 走看看