【F-python基础编程】Python 中变量赋值传递时的引用和拷贝

版权声明:转载请声名出处,谢谢 https://blog.csdn.net/u010591976/article/details/82148055

1-python的变量及其存储  

  • 引用语义:在python中,变量保存的是对象(值)的引用,我们称为引用语义。采用这种方式,变量所需的存储空间大小一致,因为变量只是保存了一个引用。也被称为对象语义和指针语义。
  • 值语义:有些语言采用的不是这种方式,它们把变量的值直接保存在变量的存储区里,这种方式被我们称为值语义,例如C语言,采用这种存储方式,每一个变量在内存中所占的空间就要根据变量实际的大小而定,无法固定下来。
  • 值语义和引用语义的区别:
    值语义: 简单的、 具体的、 可复制的
    引用语义:复杂的、 抽象的、 不可复制的
      由于python中的变量都是采用的引用语义,每个变量中都存储了这个变量的地址,而不是值本身;对于复杂的数据结构来说,里面的存储的也只只是每个元素的地址而已
     

赋值 ## 

1.数据类型重新初始化对python语义引用的影响
  变量的每一次初始化,都开辟了一个新的空间,将新内容的地址赋值给变量。在重复的初始化过程中,存储的元素地址会从地址1变成地址2.

#数据类型重新初始化对python语义引用的影响
str0 = 'abc'
print(str0)
print(id(str0))

str0 = 'ABC'
print(str0)
print(id(str0))

输出:

abc
2336735818168
ABC
2336735820520

2-数据结构内部元素变化重对python语义引用的影响
当对列表中的元素进行一些增删改的操作的时候,是不会影响到lst1列表本身对于整个列表地址的,#只会改变其内部元素的地址引用。
可是当我们对于一个列表重新初始化(赋值)的时候,就给lst1这个变量重新赋予了一个地址,覆盖了原本列表的地址,这个时候,lst1列表的内存id就发生了改变。


'''
数据结构内部元素变化重对python语义引用的影响
'''
print("---------------------------")
lst1 = [1,2,3,4,5,6,7,8,9]
print(id(lst1))
lst1.append("10")
print(lst1)
print(id(lst1))
lst1.pop()
print(lst1)
print(id(lst1))
lst1[0] = '1'
print(lst1)
print(id(lst1))
lst1 = [1,2,3,4,5,6,7,8,9]
print(lst1)
print(id(lst1))

输出:

2453182011336
[1, 2, 3, 4, 5, 6, 7, 8, 9, ‘10’]
2453182011336
[1, 2, 3, 4, 5, 6, 7, 8, 9]
2453182011336
[‘1’, 2, 3, 4, 5, 6, 7, 8, 9]
2453182011336
[1, 2, 3, 4, 5, 6, 7, 8, 9]
2453181985864

3-变量的赋值
str1的再次初始化(赋值)会导致内存地址的改变,从上图的结果我们可以看出修改了str1之后,被赋值的str2从内存地址到值都没有受到影响。

#变量的赋值
str1 = 'abc'
str2 = str1
print(str1)
print(str2)
print(id(str1))
print(id(str2))
str1 = 'ABC'
print(str1)
print(str2)
print(id(str1))
print(id(str2))

输出:

abc
abc
2240009073080
2240009073080
ABC
abc
2240009075432
2240009073080

4.复杂的数据结构中的赋值
对照内存图我们不难看出,在列表中添加新值时,列表中又多存储了一个新元素的地址,而列表本身的地址没有变化,所以lst1和lst2的id均没有改变并且都被添加了一个新的元素。


拷贝

  对于复杂的数据结构来说,赋值就等于完全共享,一个值的改变会完全被另一个值共享。
  但是有些时候,我们不想共享数据。python为这种需求提供了copy模块。提供了两种主要的copy方法,一种是普通的copy,另一种是deepcopy。前者是浅拷贝,后者为深拷贝。

 1-浅拷贝
 
浅拷贝:不管多么复杂的数据结构,浅拷贝都只会copy一层
浅拷贝的前后地址发生了变化,浅拷贝复制的是一层item的内存地址。
浅拷贝直接对列表进行操作不会对浅拷贝的列表产生影响,对列表内嵌套的其他数据结构操作,会对浅拷贝的列表产生影响。

#拷贝
#浅拷贝:
#sourceLst列表发生变化,copyLst中存储的lst内存地址不会改变;
#当sourceLst里面的元素地址发生变化时,copyLst中存储的lst内存地址不会改变,copylst列表不会发生改变
#当lst发生改变的时候,sourceLst和copyLst两个列表就都发生了改变
import copy
lst = ['str1','str2','str3','str4','str5']
sourcelst = ['str1','str2','str3','str4','str5',lst]
copyLst = copy.copy(sourcelst)
print(lst)
print(sourcelst)
print(copyLst)
print(id(sourcelst))
print(id(copyLst))

sourcelst.append("sourcestr")
print(sourcelst)
print(copyLst)
print(id(sourcelst))
print(id(copyLst))

copyLst.append("copystr")
print(sourcelst)
print(copyLst)
print(id(sourcelst))
print(id(copyLst))

sourcelst[0] = 'changesouce'
print(sourcelst)
print(copyLst)
print(id(sourcelst))
print(id(copyLst))

lst.append("changelst")
print(sourcelst)
print(copyLst)
print(id(sourcelst))
print(id(copyLst))

输出:

[‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’]
[‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, [‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’]]
[‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, [‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’]]
1382439482440
1382422406280
[‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, [‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’], ‘sourcestr’]
[‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, [‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’]]
1382439482440
1382422406280
[‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, [‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’], ‘sourcestr’]
[‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, [‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’], ‘copystr’]
1382439482440
1382422406280
[‘changesouce’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, [‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’], ‘sourcestr’]
[‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, [‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’], ‘copystr’]
1382439482440
1382422406280
[‘changesouce’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, [‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, ‘changelst’], ‘sourcestr’]
[‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, [‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, ‘changelst’], ‘copystr’]
1382439482440
sourceLst列表发生变化,copyLst中存储的lst内存地址不会改变;

  • 当sourceLst里面的元素地址发生变化时,copyLst中存储的lst内存地址不会改变,copylst列表不会发生改变
  • 当lst发生改变的时候,copyLst中存储的lst内存地址不会改变,sourceLst和copyLst两个列表就都发生了改变 import copy

    2-深拷贝
    深拷贝会完全复制原变量相关的所有数据,在内存中生成一套完全一样的内容,在这个过程中我们对这两个变量中的一个进行任意修改都不会影响其他变量。不管是对直接对列表进行操作还是对列表内嵌套的其他数据结构操作,都不会对深拷贝的列表产生影响

#深拷贝
lst = ['str1','str2','str3','str4','str5']
sourcelst = ['str1','str2','str3','str4','str5',lst]
deepcopyLst = copy.deepcopy(sourcelst)
sourcelst.append("sourcestr")
print(sourcelst)
print(deepcopyLst)
print(id(sourcelst))
print(id(cdeepcopyLst))

deepcopyLst.append("copystr")
print(sourcelst)
print(deepcopyLst)
print(id(sourcelst))
print(id(deepcopyLst))

sourcelst[0] = 'changesouce'
print(sourcelst)
print(deepcopyLst)
print(id(sourcelst))
print(id(deepcopyLst))

lst.append("changelst")
print(sourcelst)
print(deepcopyLst)
print(id(sourcelst))
print(id(deepcopyLst))

输出:

[‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, [‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’], ‘sourcestr’]
[‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, [‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’]]
2449702614088
2449685472392
[‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, [‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’], ‘sourcestr’]
[‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, [‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’], ‘copystr’]
2449702614088
2449685472392
[‘changesouce’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, [‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’], ‘sourcestr’]
[‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, [‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’], ‘copystr’]
2449702614088
2449685472392
[‘changesouce’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, [‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, ‘changelst’], ‘sourcestr’]
[‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’, [‘str1’, ‘str2’, ‘str3’, ‘str4’, ‘str5’], ‘copystr’]
2449702614088
2449685472392

参考博客:
http://www.cnblogs.com/Eva-J/p/5534037.html

猜你喜欢

转载自blog.csdn.net/u010591976/article/details/82148055