"==" 与 is
python 为 10 开辟内存空间, a与b同时指向这块内存,即a与b的值相等,a与b的id也相等.因此 a==b 与 a is b 都返回True:
a = 10 b = 10 print(a == b) #True print(id(a)) #140726165951808 print(id(b)) #140726165951808 print(a is b) #True
在[-5,256]范围内的整数会有上面代码的性能优化,而不在这范围内的数字就会重新开辟内存空间。
【实验证明,下面代码只在终端中执行Python命令行时才有效,而在执行脚本时整型的数据都会分配同一个空间】
a = 257 b = 257 print(a == b) #True print(id(a)) #139636876096528 print(id(b)) #139636905893680 print(a is b) #False
元组虽是不可变类型,但如果嵌套了可变类型(list),那么元组就变成是可变的了
t1 = (1, 2, [3, 4]) t2 = (1, 2, [3, 4]) print(t1 == t2) #True t1[-1].append(5) print(t1 == t2) #False
浅拷贝(shallow copy) 与 深拷贝(deep copy)
浅拷贝
使用数据类型本身的构造器,是浅拷贝
l1 = [1, 2, 3] l2 = list(l1) #l2 #[1, 2, 3] print(l1 == l2) #True print(l1 is l2) #False s1 = set([1, 2, 3]) s2 = set(s1) #s2 #{1, 2, 3} print(s1 == s2) #True print(s1 is s2) #False
切片也是浅拷贝
l1 = [1, 2, 3] l2 = l1[:] print(l1 == l2) #True print(l1 is l2) #False
copy.copy()浅拷贝
import copy l1 = [1, 2, 3] l2 = copy.copy(l1) print(l1 is l2) #False
对于元组,这些操作都是返回指向同一元组(1,2,3)的引用
import copy t1 = (1, 2, 3) #t2 = tuple(t1) #t2 = t1[:] #t2 = copy.copy(t1) t2 = copy.deepcopy(t1) #如果元组中不只是原子类型,比如有list,dict就可以用deepcopy print(t1 == t2) #True print(t1 is t2) #True
以下代码 l2 = list(l1)表示 l2 指向 l1浅拷贝生成的新对象, 而对象中的元素,浅拷贝就只会使用原始元素的引用(内存地址)
l1 = [[1, 2], (30, 40)]
l2 = list(l1)
由于l1与l2是两个指向不同的对象,所以 l1指向的列表增加元素不会改变 l2指向的列表
l1.append(100) print(l1) #[[1, 2, 3], (30, 40), 100] print(l2) #[[1, 2, 3], (30, 40)]
由于浅拷贝对象中的元素是引用原始元素的内存地址,因此对于可变类型(list)增加了3,l2与l1中list的是同一个引用,因此也是[1,2,3]
l1[0].append(3) print(l1) #[[1, 2, 3], (30, 40), 100] print(l2) #[[1, 2, 3], (30, 40)]
由于 tuple是不可变类型,因此修改后l1指向重新分配的一个新元组的引用。
l1[1] += (50, 60) print(l1) #[[1, 2, 3], (30, 40, 50, 60), 100] print(l2) #[[1, 2, 3], (30, 40)]
深拷贝
拷贝出来的新对象完全独立于原对象,修改操作与原对象互不影响
import copy x = [1] x.append(x) print(x) # [1, [...]] y = copy.deepcopy(x) print(y) # [1, [...]] print(x is y) #False print(x == y) #RecursionError: maximum recursion depth exceeded in comparison 递归错误
参考
https://www.cnblogs.com/wilber2013/p/4645353.html
极客时间《Python 核心技术与实战》专栏