Python 从入门到进阶之路(七)

以前的文章咱们简单介绍了一下 Python 中异常处理,本篇文章咱们来看一下 Python 中 is 和 == 的区别及深拷贝和浅拷贝。python

咱们先来看一下在 Python 中的双等号 == 。缓存

== 是比较两个对象的内容是否相等,即两个对象的“值“”是否相等,无论二者在内存中的引用地址是否同样。

is 比较的是两个实例对象是否是彻底相同,它们是否是同一个对象,占用的内存地址是否相同。即is比较两个条件:1.内容相同。2.内存中地址相同

 1 a = 10000
 2 b = 10000
 3 print(a == b)  # True
 4 print(a is b)  # True
 5 print(id(a))  # 4461408208
 6 print(id(b))  # 4461408208
 7 
 8 a = "hello world"
 9 b = "hello world"
10 print(a == b)  # True
11 print(a is b)  # True
12 print(id(a))  # 4461408208
13 print(id(b))  # 4461408208
14 
15 a = [11,22,33]
16 b = [11,22,33]
17 print(a == b)  # True
18 print(a is b)  # False
19 print(id(a))  # 4409720712
20 print(id(b))  # 4409720776

在上面的代码中,咱们分别定义了 a 和 b 两个变量,经过输出结果能够发现当变量为字符串或数字时, is 和 == 的输出结果是同样的,当为列表时 is 和 == 结果不同,经过打印两个变量的 id 值能够看出两个 id 值不同,这是因为当咱们建立列表 a 和 b 时,是分别开辟了两块内存来分别存储这两个变量,从表象上来看结果是同样的,但两个变量所指向的内存地址不同,咱们将上面的代码改成以下:编辑器

1 a = [11,22,33]
2 b = a
3 print(a == b)  # True
4 print(a is b)  # True
5 print(id(a))  # 4535062408
6 print(id(b))  # 4535062408

在上面的代码中,咱们并无直接给变量 b 赋值,而是让 b=a,这样的话 b 和 a 就指向了同一块内存,因此 a is b 就为 True 了。函数

上面的代码我是在 PyCharm 编辑器中实现的,可是在终端命令行实现的话结果倒是不同的,以下:优化

 1 >>> a = 10000
 2 >>> b = 10000
 3 >>> a == b
 4 True
 5 >>> a is b
 6 False
 7 >>> id(a)
 8 4360555120
 9 >>> id(b)
10 4360555216

当咱们将 a 和 b 的值变小时,以下:spa

 1 >>> a = 100
 2 >>> b = 100
 3 >>> a == b
 4 True
 5 >>> a is b
 6 True
 7 >>> id(a)
 8 4357367984
 9 >>> id(b)
10 4357367984

形成上面的缘由是由于python对小整数在内存中直接建立了一份,不会回收,全部建立的小整数变量直接从对象池中引用他便可。可是注意Python仅仅对比较小的整数对象进行缓存(范围为范围[-5, 256])缓存起来,而并不是是全部整数对象。也就说只有在这个[-5,256]范围内建立的变量值使用is比较时候才会成立。命令行

在 PyCharm 中,当值超过 256 时 is 和 == 的输出结果还是同样,这是由于解释器也作了一部分优化,对于数字和字符串这类变量都进行了缓存。code

咱们再来看一下在终端命令行中当变量为字符串时:对象

 1 >>> a = "hello world"
 2 >>> b = "hello world"
 3 >>> a == b
 4 True
 5 >>> a is b
 6 False
 7 >>> id(a)
 8 4359747248
 9 >>> id(b)
10 4361247408
 1 >>> a = "hello"
 2 >>> b = "hello"
 3 >>> a == b
 4 True
 5 >>> a is b
 6 True
 7 >>> id(a)
 8 4361199040
 9 >>> id(b)
10 4361199040

经过输出结果能够看出,在命令行中当变量为简单字符串时输出结果一致,不然输出结果不一致,这是因为 Python 对简单字符串对象也进行了缓存,这样作的意义是能够优化代码的运行速度,减小内存消耗。blog

 

在上面的代码中,咱们让 a=b 实际上是一种浅拷贝的过程,他们指向的是同一块内存,当咱们改变其中一个变量时,另外一个也会变,以下:

1 a = [11,22,33]
2 b = a
3 a[0] = 123
4 print(a)  # [123, 22, 33]
5 print(b)  # [123, 22, 33]

在 Python 中海油深拷贝,它是从新开辟一块区域用来存储变量的,以下:

 1 import copy
 2 
 3 a = [11, 22, 33]
 4 b = a
 5 c = [11, 22, 33]
 6 d = copy.deepcopy(a)
 7 print(a == b, a is b)  # True True
 8 print(a == c, a is c)  # True False
 9 print(a == d, a is d)  # True False
10 
11 a[0] = 123
12 print(a)  # [123, 22, 33]
13 print(b)  # [123, 22, 33]
14 print(c)  # [11, 22, 33]
15 print(d)  # [11, 22, 33]

在上面的代码中咱们引入了一个 copy 的模块,引入模块这个以前的文章没有提到,后续会单独说一下。

在 copy 模块中有一个 deepcopy() 的方法,从上面的代码中能够看出 deepcopy() 的方法就至关于 c=[11,22,33] 这样从新开辟一块区域来存储变量,当 a 变量改变时,浅拷贝的内容 b 会随之改变,可是深拷贝的内容 d 并非指向 a 的内存地址,因此不会改变。

 

在 copy 的模块中海油一个 copy() 方法,它在某些方面看起来和 deepcopy() 方法是同样的,其实不同,以下:

import copy

a = [11, 22, 33]
b = copy.copy(a)
c = copy.deepcopy(a)
a[0] = 123
print(a)  # [123, 22, 33]
print(b)  # [11, 22, 33]
print(c)  # [11, 22, 33]

从上面的输出结果看,当 a 变量修改以后,b 变量和 c 变量同样没有改变,那 copy() 和 deepcopy() 到底有什么区别呢,咱们再看下面的代码:

1 import copy
2 
3 a = [11, 22, [123,456]]
4 b = copy.copy(a)
5 c = copy.deepcopy(a)
6 a[2][0] = 789
7 print(a)  # [11, 22, [789, 456]]
8 print(b)  # [11, 22, [789, 456]]
9 print(c)  # [11, 22, [123, 456]]

从上面的输出结果能够看出,b 变量随 a 变量的变化而变化了,而 c 变量没有。

很显然这时 copy() 函数拷贝的值随着原对象的值修改了,而 deepcopy() 的值没有随着原对象的值修改。主要是由于 deepcopy()  会将复杂对象的每一层复制一个单独的个体出来对于 copy() 函数要慎用,慎用。

相关文章
相关标签/搜索