1.is和==的区别
【总结】
is和== 两种运算符在应用上的本质区别是什么?
1). Python中对象的三个基本要素,分别是:id(身份标识)、type(数据类型)和value(值)。
2). is和==都是对对象进行比较判断作用的,但对对象比较判断的内容/范围并不相同。
3). ==用来比较判断两个对象的value(值)是否相等(type和value)
is也被叫做同一性运算符, 会判断id是否相同(id, type 和value)
2.深浅拷贝
首先来看没有拷贝的情况:
li = [1, 2, 3, 4, 5]
li1 = li
print(li, id(li))
print(li1, id(li1))
可以看到,li和li1指向同一块内存空间
对任意一个变量做修改, 另一个变量同时受到影响。 所以没有成功拷贝
再看浅拷贝:
import copy
li = [1, 2, 3, 4, 5]
li2 = copy.copy(li) #也可以li2 = li[:]
print(li, id(li))
print(li2, id(li2))
可以看到两个变量分别指向内存中的两块空间
li[0] = 100
print(li)
print(li2)
对li列表添加元素100
可以看到li中的内容变了,而li2并没有受影响。
深拷贝:
什么场合下需要使用深拷贝呢?先看下面的代码:
scores = [100, 100, [100, 100, 100]]
scores1 = scores[:] #或者导入copy模块,调用copy.copy方法浅拷贝
print(scores, id(scores))
print(scores1, id(scores1))
scores[-1][0] = 200
print(scores)
print(scores1)
列表scores中还嵌套了一个小列表,scores1浅拷贝了scores,虽然两个变量在内存中的地址空间不一样,但是列表中的小列表占的是内存中同一块空间,对scores列表中的小列表进行修改后,scores1也同时被修改了。因此需要引入深拷贝的概念。深拷贝需要使用的是deepcopy方法。
import copy
scores = [100, 100, [100, 100, 100]]
scores1 = copy.deepcopy(scores)
print(scores, id(scores))
print(scores1, id(scores1))
scores[-1][0] = 200
print(scores)
print(scores1)
深拷贝调用了copy模块中的deepcopy方法,同样对scores列表中的小列表进行修改,修改之后,scores1列表并没有受到任何影响
特殊情况:(了解即可)
元组与str、int等数据类型一样,都是不可变数据类型。对于不可变数据类型,浅拷贝与深拷贝都是指向这个地址,并不拷贝。
tuple = (1,2,3,4)
print('浅拷贝'.center(20,'*'))
tuple1 = copy.copy(tuple)
print('tuple:',tuple,id(tuple))
print('tuple1',tuple1,id(tuple1))
print('深拷贝'.center(20,'*'))
tuple2 = copy.deepcopy(tuple)
print('tuple:',tuple,id(tuple))
print('tuple2',tuple2,id(tuple2))
因此深浅拷贝之后,都指向内存中同一块地址。
而如果元组中,嵌套了可变数据类型,例如列表
tuple = (1,2,3,4,[5,6,7,8])
print('浅拷贝'.center(20,'*'))
tuple1 = copy.copy(tuple)
print('tuple:',tuple,id(tuple))
print('tuple1',tuple1,id(tuple1))
print('深拷贝'.center(20,'*'))
tuple2 = copy.deepcopy(tuple)
print('tuple:',tuple,id(tuple))
print('tuple2',tuple2,id(tuple2))
此时,浅拷贝之后,tuple和tuple1指向内存中同一块地址;深拷贝之后,tuple和tuple2指向不同的两块地址。
【总结】
- 没有拷贝: li1 = li
- 浅拷贝:只拷贝第一层
li2 = li[:]
li3 = copy.copy(li) - 深拷贝:拷贝嵌套层次中的所有可变类型
li4 = copy.deepcopy(li)