(关于学习廖雪峰Python教程的一些个人总结)
Python是动态语言。
可以把任意数据类型赋值给变量,无需提前声明变量类型,同一个变量可以反复赋值,而且可以是不同类型的变量。
下面引用廖雪峰Python教程的简单例子,描述变量存储过程:
当我们写
a = 'ABC'时,Python解释器干了两件事情:
在内存中创建了一个'ABC'的字符串;在内存中创建了一个名为a的变量,并把它指向'ABC'。下面程序
a = 'ABC' b = a a = 'XYZ' print(b) # >>> ABC执行过程:
执行a = 'ABC',解释器创建了字符串'ABC'和变量a,并把a指向'ABC':
执行b = a,解释器创建了变量b,并把b指向a指向的字符串'ABC':
执行a = 'XYZ',解释器创建了字符串’XYZ’,并把a的指向改为'XYZ',但b并没有更改:
所以,最后打印变量b的结果是'ABC'了。
Python当中对于拷贝,按照拷贝数据类型分为两种类型。一种是数字和字符串的拷贝,另一种就是列表、元组、字典等其他数据结构类型的拷贝。
当然按照深浅也分深拷贝和浅拷贝。
举例:
a1 = 123 a2 = 123 print(id(a1)) print(id(a2))结果:(在你的电脑试验和这里的地址肯定不同)
140723824476816 140723824476816原因是Python有一个重用机制,对于同一个数字,Python并不会开辟一块新的内存空间,而是维护同一块内存地址,a1,a2变量指向数字123的地址。等同于a2 = a1,使用字符串赋值也是同理。
结论:对于通过用 = 号赋值,数字和字符串在内存当中用的都是同一块地址。
举例:
import copy # 使用浅拷贝需要导入copy模块 a1 = 123 a3 = copy.copy(a1) # 使用copy模块里的copy()函数就是浅拷贝 print(id(a1)) print(id(a3))结果:(在你的电脑试验和这里的地址肯定不同)
140723824476816 140723824476816发现地址还是一样。
结论:对于浅拷贝,数字和字符串在内存当中用的也是同一块地址,和上面讲的原理相同。
举例:
import copy a1 = 123 a4 = copy.deepcopy(a1) # 深拷贝是用copy模块里的deepcopy()函数 print(id(a1)) print(id(a4))结果:(在你的电脑试验和这里的地址肯定不同)
140723824476816 140723824476816发现地址还是一样。
结论:对于深拷贝,数字和字符串在内存当中用的也是同一块地址,和上面讲的原理相同。
综上所述,对于数字和字符串的赋值、浅拷贝、深拷贝在内存当中用的都是同一块地址。
举例:
dict1 = {'k1': 'wu', 'k2': 123, 'k3': {1: 'alex', 2: 678}} dict2 = dict1 print(id(dict1)) print(id(dict2))结果:(在你的电脑试验和这里的地址肯定不同)
2331901131440 2331901131440dict2变量只是指向了同一份字典数据的地址,如下图所示:
理解了上面的图我们看一下下面的代码:
dict1 = dict1['k3'] dict2 = dict1 dict2[3] = 'hiahia' print(dict1)我们逐步看怎么执行的:
dict1 = dict1['k3'] dict2 = dict1 dict2[3] = 'hiahia' print(dict1)所以结果是:
{1: 'alex', 2: 678, 3: 'hiahia'}举例:
import copy dict1 = {"k1": "wu", "k2": 123, "k3": {1: 'alex', 2: 678}} dict3 = copy.copy(dict1) # 浅拷贝 print("第一层字典的内存地址:") print(id(dict1)) print(id(dict3)) print("第二层嵌套的列表的内存地址:") print(id(dict1["k3"])) print(id(dict3["k3"]))结果:(在你的电脑试验和这里的地址肯定不同)
第一层字典的内存地址: 2331901131872 2331901132088 第二层嵌套的列表的内存地址: 2331901155272 2331901155272结果发现字典第一层确实被拷贝了,变成了两个,但第二层还是共用相同的数据,如下图:
结论:所以对于浅拷贝,字典、列表、元组等类型,它们只拷贝第一层地址。
举例:
import copy dict1 = {"k1": "wu", "k2": 123, "k3": {1: 'alex', 2: 678}} dict4 = copy.deepcopy(dict1) # 深拷贝 print("第一层字典的内存地址:") print(id(dict1)) print(id(dict4)) print("第二层嵌套的列表的内存地址:") print(id(dict1["k3"])) print(id(dict4["k3"])) print("第三层嵌套的列表的内存地址:") print(id(dict1["k3"][1])) print(id(dict4["k3"][1]))结果:(在你的电脑试验和这里的地址肯定不同)
第一层字典的内存地址: 2331901131872 2331901132376 第二层嵌套的列表的内存地址: 2331901155272 2331901091976 第三层嵌套的列表的内存地址: 2331901150912 2331901150912发现一二层被拷贝了,最底层的数字和字符串数据依然共用,如下图:
结论:对于深拷贝,字典、列表、元组等类型,它里面嵌套多少层,就会拷贝多少层出来,但是最底层的数字和字符串地址不变。