不知道大家还记得,之前我们讲过的可变数据类型,还有不可变数据类型吗?如果忘了,可以再回顾一下系列第八章。
我们举例来说明一下,可变和不可变的运用。
不可变例子:
string_1 = "ABCDEF"
string_2 = string_1
print("变量string_1现在的值为:{}".format(string_1))
print("变量string_1的内存ID为:{}".format(id(string_1)))
print("变量string_2现在的值为:{}".format(string_2))
print("变量string_2的内存ID为:{}".format(id(string_2)))
string_2 = "123456"
print("分割线".center(33, "="))
print("变量string_1现在的值为:{}".format(string_1))
print("变量string_1的内存ID为:{}".format(id(string_1)))
print("变量string_2现在的值为:{}".format(string_2))
print("变量string_2的内存ID为:{}".format(id(string_2)))
结果为:
变量string_1现在的值为:ABCDEF
变量string_1的内存ID为:2691686984368
变量string_2现在的值为:ABCDEF
变量string_2的内存ID为:2691686984368
===============分割线===============
变量string_1现在的值为:ABCDEF
变量string_1的内存ID为:2691686984368
变量string_2现在的值为:123456
变量string_2的内存ID为:2691687039216
- 在这个例子中,我们先声明赋值了一个变量string_1,我们可以说,变量string_1代表的内存ID为2691686984368
- 然后又声明了一个变量string_2且把变量string_1赋值给了string_2,我们也可以认为,string_1把自己代表的内存ID也给了string_2,所以变量string_2代表的内存ID也为2691686984368
- 接下来,我们又把“123456”这个新的字符串赋值给了变量string_2。
- 因为字符串类型是不可变类型的,所以新的字符串“123456”的内存ID跟“ABCDEFG”的内存ID是不一样的(意思就是新建的不可变类型,要使用新的一段内存空间来存储新的数据)。所以“123456”的内存ID为2691687039216
- 这就相当于,刚开始,string_1和string_2都代表着“ABCDEFG”,然后我们把string_2改为了“123456”。
- 从结果上来看,string_2的修改不会影响到string_1的值。
- 也就是说,在不可变数据类型中,其他变量的修改,不会影响到当前变量。
可变类型例子:
string_1 = ["A", "B", "C"]
string_2 = string_1
print("变量string_1现在的值为:{}".format(string_1))
print("变量string_1的内存ID为:{}".format(id(string_1)))
print("变量string_2现在的值为:{}".format(string_2))
print("变量string_2的内存ID为:{}".format(id(string_2)))
string_2.extend([1, 2, 3])
print("分割线".center(33, "="))
print("变量string_1现在的值为:{}".format(string_1))
print("变量string_1的内存ID为:{}".format(id(string_1)))
print("变量string_2现在的值为:{}".format(string_2))
print("变量string_2的内存ID为:{}".format(id(string_2)))
结果为:
变量string_1现在的值为:['A', 'B', 'C']
变量string_1的内存ID为:2330274451848
变量string_2现在的值为:['A', 'B', 'C']
变量string_2的内存ID为:2330274451848
===============分割线===============
变量string_1现在的值为:['A', 'B', 'C', 1, 2, 3]
变量string_1的内存ID为:2330274451848
变量string_2现在的值为:['A', 'B', 'C', 1, 2, 3]
变量string_2的内存ID为:2330274451848
- 在这个例子中,我们先声明赋值了一个变量string_1,我们可以说,变量string_1代表的内存ID为2330274451848
- 然后又声明了一个变量string_2且把变量string_1赋值给了string_2,我们也可以认为,string_1把自己代表的内存ID也给了string_2,所以变量string_2代表的内存ID也为2330274451848
- 接下来,我们在string_2中新添加了几个元素[1,2,3]。
- 如果按照之前的想法来说,修改变量string_2应该不影响string_1,对吧?这是不对的。
- 因为列表为可变数据类型,所以列表的修改,不会再新建一个内存空间来存储值,而是在原有的内存ID代表的内存空间内进行修改。
- 这就是为什么,我们修改了变量string_2的值,会影响到变量string的值。
- 从内存ID上来看,我们也可以看出来,两个变量从头到尾,都是同一个内存ID。
- 从结果上来看,string_2的修改会影响到string_1的值。
- 也就是说,在可变数据类型中,其他变量的修改,会可能会影响到当前变量。
- 既然可变类型的变量会出现这种情况,那么我们应该如果解决呢?
- 大家可以再查看一下,上篇我们在讲列表的时候,列表有一个函数copy,是用来复制列表的。
- 它的具体含义,就是新建一个内存空间,把我们想要修改的变量复制一份。
- 这样我们再修改复制好的变量后,就不会影响到原来的变量了。
copy函数例子:
string_1 = ["A", "B", "C"]
string_2 = string_1.copy()
print("变量string_1现在的值为:{}".format(string_1))
print("变量string_1的内存ID为:{}".format(id(string_1)))
print("变量string_2现在的值为:{}".format(string_2))
print("变量string_2的内存ID为:{}".format(id(string_2)))
string_2.extend([1, 2, 3])
print("分割线".center(33, "="))
print("变量string_1现在的值为:{}".format(string_1))
print("变量string_1的内存ID为:{}".format(id(string_1)))
print("变量string_2现在的值为:{}".format(string_2))
print("变量string_2的内存ID为:{}".format(id(string_2)))
结果为:
变量string_1现在的值为:['A', 'B', 'C']
变量string_1的内存ID为:1927441043848
变量string_2现在的值为:['A', 'B', 'C']
变量string_2的内存ID为:1927441044360
===============分割线===============
变量string_1现在的值为:['A', 'B', 'C']
变量string_1的内存ID为:1927441043848
变量string_2现在的值为:['A', 'B', 'C', 1, 2, 3]
变量string_2的内存ID为:1927441044360
- 从这个例子中,我们使用了copy函数,对变量string_1进行了复制,复制给了变量string_2
- 我们再用id函数来查看内存id的时候,就会发现变量string_1的内存ID和变量string_2的内存ID是完全不一样的
- 然后我们再修改变量string_2的值的时候,就不会影响到变量string_1了
- 我们可以使用可变类型的这些特性来做一些事情
- 不使用copy函数的时候的列表,我们可以认为是一条工厂流水线,两个工人一起在这条流水线上工作,这两个工人,都会影响到这条流水线上的产品
- 使用copy函数后,就相当于两条流水线,两个工人各自负责一条流水线,不会互相影响。