== 与 is 的区别
- == :判断 值,比较两个对象是否相等
- is :判断 地址,比较两个引用是否指向了同一个对象(引用比较)
赋值、深拷贝、浅拷贝的区别
首先,不可变数据类型的内存都指向同一个地址,所以深拷贝和浅拷贝对于不可变数据类型而言都是无意义的。
对于不可变数据类型:
import copy
# 深拷贝
a = 'python'
b = copy.deepcopy(a)
print(a, id(a)) # python 2796288573600
print(b, id(b)) # python 2796288573600
# 浅拷贝
c = copy.copy(a)
print(a, id(a)) # python 2796288573600
print(c, id(c)) # python 2796288573600
赋值
是对原变量的完全复制,内存地址一样,如果原来的改变,后面的也会跟着变。
x = [123, 456, 789]
y = x
print(x, id(x)) # [123, 456, 789] 1885210370632
print(y, id(y)) # [123, 456, 789] 1885210370632
x[0] = 1
print(x, id(x)) # [1, 456, 789] 1885210370632
print(y, id(y)) # [1, 456, 789] 1885210370632
深拷贝
对于可变数据类型:
import copy
a = [123, [1, 2, 3]]
b = copy.deepcopy(a)
print(a, id(a), id(a[0]), id(a[1])) # [123, [1, 2, 3]] 2734749304648 140719688872400 2734749304584
print(b, id(b), id(b[0]), id(b[1])) # [123, [1, 2, 3]] 2734749395720 140719688872400 2734749502728
a[1][0] = 5 # 修改嵌套列表的元素
print(a, id(a), id(a[0]), id(a[1])) # [123, [5, 2, 3]] 2734749304648 140719688872400 2734749304584
print(b, id(b), id(b[0]), id(b[1])) # [123, [1, 2, 3]] 2734749395720 140719688872400 2734749502728
我们可以看到,深拷贝是直接创建了一个新的对象,所以地址不同,将原对象所有的值/元素拷贝过来,而且是对其所有层次的拷贝(包括嵌套列表)
- 将原对象的“ 值/元素 ”赋给新对象,新对象中元素的地址与原对象的 地址不同
- 是对原对象 所有层次 的拷贝(递归)
- 与原对象没有任何关系,如果原对象发生变化,深拷贝后的新对象 不会发生改变
浅拷贝
对于可变数据类型:
import copy
a = [123, [1, 2, 3]]
b = copy.copy(a)
print(a, id(a), id(a[0]), id(a[1])) # [123, [1, 2, 3]] 2944705742536 140719688872400 2944705742472
print(b, id(b), id(b[0]), id(b[1])) # [123, [1, 2, 3]] 2944705837704 140719688872400 2944705742472
a[1][0] = 5 # 修改嵌套列表的元素
print(a, id(a), id(a[0]), id(a[1])) # [123, [5, 2, 3]] 2944705742536 140719688872400 2944705742472
print(b, id(b), id(b[0]), id(b[1])) # [123, [5, 2, 3]] 2944705837704 140719688872400 2944705742472
我们可以看到,两个列表的元素指向同一地址,拷贝的只是原列表元素的引用。
当我们修改嵌套列表的元素时,新列表中的嵌套列表也会发生改变,这是因为浅拷贝只拷贝了表面一层列表,而嵌套列表并没有进行拷贝,所以修改嵌套列表之后,新列表也会变。
- 将原对象的 引用 赋给新对象,新对象中元素的地址与原对象的 地址相同
- 是对原对象 顶层 的拷贝(表面一层)
- 由于只拷贝了表面一层,当原对象中的嵌套对象发生改变时,新对象也 会发生改变