赋值
Python中对象的赋值是简单的对象引用(可以把这个对象看成一个盒子,赋值是给这个盒子上贴不同的标签,指向的都是这个盒子对象)
a = 'haha'
b = a
id(a) # output: 140640656233712
id(b) # output: 140640656233712
拷贝
浅拷贝
Python中序列类型的拷贝默认为浅拷贝,可以使用以下几种方式进行拷贝:
- 完全的切片操作[:]
- 利用工厂函数,list(),dict()等
- 使用copy模块的copy函数
person = ['name', ['savings', 100.00]]
hubby = person[:] # 切片拷贝
wifey = list(person) # 利用工厂函数拷贝
[id(x) for x in (person, hubby, wifey)]
output: [140640651046408, 140640651435848, 140640650741832] #可以看到拷贝了2个新的对象
# 这3个对象id不一致,但是他们的元素id值一样
[id(x) for x in person]
output: [140640753298320, 140640654842952]
[id(x) for x in hubby]
output: [140640753298320, 140640654842952]
[id(x) for x in wifey]
output: [140640753298320, 140640654842952]
hubby[0] = 'jay'
wifey[0] = 'lucy'
hubby, wifey
output: ['jay', ['savings', 100.00]], ['lucy', ['savings', 100.00]]
hubby[1][1] = 50.00
hubby, wifey
output: ['jay', ['savings', 50.00]], ['lucy', ['savings', 50.00]]
通过上面的例子可以看到,通过改变hubby[1][1]的值,wifey[1][1]的值也被改变了,这是因为对一个对象进行浅拷贝其实是新创建了一个类型和原对象一样,内容为原对象的引用。
person这个对象有2个元素,不可变对象字符串和可变对象列表,当hubby[0] = 'jay'时,由于字符串是不可变对象,相当于新创建了一个对象‘jay’,赋值给了hubby[1],wifey[0] = 'lucy',也是新创建一个'lucy'对象赋值给了wifey。hubby[1][1]=50.00时,因为hubby[1]为一个列表可变对象,所以原地更改了这个列表对象的值,id并没有改变,所以对应的person[1],wifey[1]中的值也发生了改变
深拷贝
对容器元素中的原有的非原子对象进行全新的拷贝(id值不一样),使用copy模块的deepcopy函数进行深拷贝
person = ['name', ['savings', 100.00]]
hubby = person # 赋值操作
import copy
wifey = copy.deepcopy(person)
[id(x) for x in (person, hubby, wifey)]
output: [140640651021896, 140640651021896, 140640651420744]
[id(x) for x in person]
output: [140640753298320, 140640654842952]
[id(x) for x in hubby]
output: [140640753298320, 140640654842952] # 因为上面做的是赋值操作所以id同person一致
[id(x) for x in wifey]
output: [140640753298320, 140640652252360] # 字符串的id同person[0]一致,列表的id同person[1]的不一致,所以只对深拷贝只对非原子对象进行了全新的拷贝
hubby[0] = 'jay'
wifey[0] = 'lucy'
hubby[1][1] = 50.00
hubby, wifey
output: ['jay', ['savings', 50.00]], ['lucy', ['savings', 100.00]]
- 非容器类型(比如数字、字符串这类原子类型的对象)没有拷贝这一说,浅拷贝是用完全切片操作来完成的
- 如果元祖变量只包含原子类型的对象,对它进行深拷贝将不会进行
原子类型:
Python中以存储模型来对对象进行划分,分为原子类型和容器类型,即看这种类型的对象能保存多少个对象。一个能保存单个对象的类型我们称为原子类型或标量存储类型,可容纳多个对象的类型我们称为容器类型。
网友评论