来讲讲python中赋值和深浅拷贝的问题
赋值
我们取两个变量x,y,并赋给他们同样的值,打印他们的id地址。
x = 3232
y = 3232
print(id(x)) #2622651027248
print(id(y)) #2622651027248
x = 'sdsd'
y = 'sdsd'
print(id(x)) #2003245593072
print(id(y)) #2003245593072
结果内存地址一样,再来看看列表
x = ['sdsd','sd']
y = ['sdsd','sd']
print(id(x)) #2340304474376
print(id(y)) #2340304474504
内存地址不同,这里不难得出,赋值给不同的变量相同的值(可变数据类型),内存地址不变,因为python有一个重用机制,对于同一个数字或字符串,python并不会开辟一块新的内存空间,而是继续用之前开辟的空间。
再试下给一个变量(字符串,数字)赋值,然后把这个变量赋给另一个变量,这里直接试两个地址是否一样。
l1 = 'python'
l2 = l1
print(id(l1)==id(l2)) # True
l1 = 'java'
print(id(l1)==id(l2)) # False
我们可以看到,如果是l1赋值给l2,两个变量指向的是同一个地址,而如果我们再给l1赋新值,地址则不同。
那给可变数据类型(字典,列表)变量赋值呢?
l1 = [1, 2, ['python', 'c', 'c++','java']]
l2 = l1
l2[1]='0'
l2[2][2]='php'
l2[2].append('ruby')
print(l1) # [1, '0', ['python', 'c', 'php', 'java', 'ruby']]
print(id(l1)==id(l2)) # True
对列表的增改操作,l2发生了变化,而内存地址没有变化。
结论:赋值如果是数字和字符串在内存当中用的都是同一块地址,对于字典、列表等类型用的内存地址不会变化。
浅拷贝
拷贝我们需要导入copy模块
import copy
a = 123456
b = copy.copy(a)
print(id(a) == id(b)) #True
字符串的浅拷贝内存地址一样,再看看其他数据类型
import copy
a = [1, 2, ['python', 'c', 'c++','java'], {1:2, 3:4}]
b = copy.copy(a)
print(id(a) == id(b)) #False
a[2].append('ruby')
print(a) #[1, 2, ['python', 'c', 'c++', 'java', 'ruby'], {1: 2, 3: 4}]
print(b) #[1, 2, ['python', 'c', 'c++', 'java', 'ruby'], {1: 2, 3: 4}]
print(id(a[2]) == id(b[2])) #True
a[-1].setdefault(5,6)
print(a) #[1, 2, ['python', 'c', 'c++', 'java', 'ruby'], {1: 2, 3: 4, 5: 6}]
print(b) #[1, 2, ['python', 'c', 'c++', 'java', 'ruby'], {1: 2, 3: 4, 5: 6}]
print(id(a[-1]) == id(b[-1])) #True
a.append(5)
print(a) #[1, 2, ['python', 'c', 'c++', 'java', 'ruby'], {1: 2, 3: 4, 5: 6}, 5]
print(b) #[1, 2, ['python', 'c', 'c++', 'java', 'ruby'], {1: 2, 3: 4, 5: 6}]
print(id(a) == id(b)) #False
可以看到浅拷贝是重新开辟空间,并且只拷贝第一层,内层不拷贝,内层指向的地址都一样,而第一层的地址不同
深拷贝
字符串数字深拷贝
import copy
a = 123456
b = copy.deepcopy(a)
print(id(a) == id(b)) #True
地址一样
其他数据类型,这里用的代码和上面的基本一样:
import copy
a = [1, 2, ['python', 'c', 'c++','java'], {1:2, 3:4}]
b = copy.deepcopy(a)
print(id(a) == id(b)) #False
a[2].append('ruby')
print(a) #[1, 2, ['python', 'c', 'c++', 'java', 'ruby'], {1: 2, 3: 4}]
print(b) #[1, 2, ['python', 'c', 'c++', 'java'], {1: 2, 3: 4}]
print(id(a[2]) == id(b[2])) #False
a[-1].setdefault(5,6)
print(a) #[1, 2, ['python', 'c', 'c++', 'java', 'ruby'], {1: 2, 3: 4, 5: 6}]
print(b) #[1, 2, ['python', 'c', 'c++', 'java'], {1: 2, 3: 4}]
print(id(a[-1]) == id(b[-1])) #False
a.append(5)
print(a) #[1, 2, ['python', 'c', 'c++', 'java', 'ruby'], {1: 2, 3: 4, 5: 6}, 5]
print(b) #[1, 2, ['python', 'c', 'c++', 'java', 'ruby'], {1: 2, 3: 4}]
print(id(a) == id(b)) #False
内外层地址都不同,所以深拷贝在内存完完全全自己开辟了一个新空间把原来的被拷贝对象从内到外都拷贝了过来,原被拷贝对象的修改不影响拷贝的变量内的值
切片
最后说下切片,切片是浅拷贝
a = [1,2,3, [3,4,5]]
b = a[:]
a[-1].append('c')
print(a)
print(b)
print(id(a) == id(b))
print(id(a[-1]) == id(b[-1]))
输出结果:
[1, 2, 3, [3, 4, 5, 'c']]
[1, 2, 3, [3, 4, 5, 'c']]
False
True