copy.copy() 浅拷贝
copy.deepcopy() 深拷贝
其次我们还需要知道
python中对象包含三要素:id(唯一标识一个对象)、type(标识对象的类型)、value(是对象的值)。
下面详细看看 赋值、浅拷贝、深拷贝之间的区别:
一、赋值
n4 = n3 = n2 = n1 = "123/'wu'" # 表示的变量的赋值,在内存中如下显示:
可以发现,赋值操作只是创建了与原来变量相同类型的变量,但是,变量中的内容也就是value没有产生新的。所以在赋值的时候,所有的变量的id都是相同的,同样在程序中也可以证明【用 id(name) 来查看变量的地址】
n4 = n3 = n2 = n1 = "123/'wu'"
print("id of n4",id(n4))
print("id of n3",id(n3))
print("id of n2",id(n2))
print("id of n1",id(n1))
运行结果:
id of n4 2054155629040
id of n3 2054155629040
id of n2 2054155629040
id of n1 2054155629040
发现,变量的地址也就是id是没有变的。
二、浅拷贝
浅拷贝是新创建了一个跟原对象一样的类型,但是其内容是对原对象元素的引用。这个拷贝的对象本身是新的,但内容不是。拷贝序列类型对象(列表\元组)时,默认是浅拷贝。
浅拷贝在内存中只是额外创建了第一层的数据:
import copy
n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]}
n3 = copy.copy(n1)
上述程序在内存中可以显示为:
在程序中运行观察:
import copy
n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]}
n3 = copy.copy(n1)
print('两个变量的地址:')
print('id of n1: ',id(n1))
print('id of n3: ',id(n3))
print('变量中的键对应的值的地址:')
print("n1 中 键'k3'对应值的地址: ",id(n1["k3"]))
print("n3 中 键'k3'对应值的地址: ",id(n3["k3"]))
运行结果:
两个变量的地址:
id of n1: 2054248643784
id of n3: 2054249278024
变量中的键对应的值的地址:
n1 中 键'k3'对应值的地址: 2054249278344
n3 中 键'k3'对应值的地址: 2054249278344
可以发现,由于创建了新的第一层的数据,所以两个变量的地址是不一样的,但是由于除了第一层之外的所有数据都没有复制,所以,其他数据的地址(ID)是没有变的。
三、深拷贝
深拷贝,在内存中将所有的数据重新创建一份(排除最后一层,即:python内部对字符串和数字的优化),如下图:
import copy
n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]}
n3 = copy.deepcopy(n1)
print('两个变量的地址:')
print('id of n1: ',id(n1))
print('id of n3: ',id(n3))
print('变量中的键对应的值的地址:')
print("n1 中 键'k3'对应值的地址: ",id(n1["k3"]))
print("n3 中 键'k3'对应值的地址: ",id(n3["k3"]))
运行结果:
两个变量的地址:
id of n1: 2054248643656
id of n3: 2054249277640
变量中的键对应的值的地址:
n1 中 键'k3'对应值的地址: 2054248736008
n3 中 键'k3'对应值的地址: 2054249278408
与浅拷贝的结果对比可以发现,深拷贝中的 "k3" 对应的值的地址不同,也就是说 创建了新的数据