Python 从入门到进阶之路(七)
之前的文章我们简单介绍了一下 Python 中异常处理,本篇文章我们来看一下 Python 中 is 和 == 的区别及深拷贝和浅拷贝。
我们先来看一下在 Python 中的双等号 == 。
== 是比较两个对象的内容是否相等,即两个对象的“值”是否相等,不管两者在内存中的引用地址是否一样。
is 比较的是两个实例对象是不是完全相同,它们是不是同一个对象,占用的内存地址是否相同。即is比较两个条件:1.内容相同。2.内存中地址相同
a = 10000
b = 10000
print(a == b) # True
print(a is b) # True
print(id(a)) #
print(id(b)) # a = "hello world"
b = "hello world"
print(a == b) # True
print(a is b) # True
print(id(a)) #
print(id(b)) # a = [11,22,33]
b = [11,22,33]
print(a == b) # True
print(a is b) # False
print(id(a)) #
print(id(b)) #
在上面的代码中,我们分别定义了 a 和 b 两个变量,通过输出结果可以发现当变量为字符串或数字时, is 和 == 的输出结果是一样的,当为列表时 is 和 == 结果不一样,通过打印两个变量的 id 值可以看出两个 id 值不一样,这是由于当我们创建列表 a 和 b 时,是分别开辟了两块内存来分别存储这两个变量,从表象上来看结果是一样的,但两个变量所指向的内存地址不一样,我们将上面的代码改为如下:
a = [11,22,33]
b = a
print(a == b) # True
print(a is b) # True
print(id(a)) #
print(id(b)) #
在上面的代码中,我们并没有直接给变量 b 赋值,而是让 b=a,这样的话 b 和 a 就指向了同一块内存,所以 a is b 就为 True 了。
上面的代码我是在 PyCharm 编辑器中实现的,但是在终端命令行实现的话结果却是不一样的,如下:
>>> a = 10000
>>> b = 10000
>>> a == b
True
>>> a is b
False
>>> id(a)
4360555120
>>> id(b)
4360555216
当我们将 a 和 b 的值变小时,如下:
>>> a = 100
>>> b = 100
>>> a == b
True
>>> a is b
True
>>> id(a)
4357367984
>>> id(b)
4357367984
造成上面的原因是因为python对小整数在内存中直接创建了一份,不会回收,所有创建的小整数变量直接从对象池中引用他即可。但是注意Python仅仅对比较小的整数对象进行缓存(范围为范围[-5, 256])缓存起来,而并非是所有整数对象。也就说只有在这个[-5,256]范围内创建的变量值使用is比较时候才会成立。
在 PyCharm 中,当值超过 256 时 is 和 == 的输出结果仍是一样,这是因为解释器也做了一部分优化,对于数字和字符串这类变量都进行了缓存。
我们再来看一下在终端命令行中当变量为字符串时:
>>> a = "hello world"
>>> b = "hello world"
>>> a == b
True
>>> a is b
False
>>> id(a)
4359747248
>>> id(b)
4361247408
>>> a = "hello"
>>> b = "hello"
>>> a == b
True
>>> a is b
True
>>> id(a)
4361199040
>>> id(b)
4361199040
通过输出结果可以看出,在命令行中当变量为简单字符串时输出结果一致,否则输出结果不一致,这是由于 Python 对简单字符串对象也进行了缓存,这样做的意义是可以优化代码的运行速度,减少内存消耗。
在上面的代码中,我们让 a=b 其实是一种浅拷贝的过程,他们指向的是同一块内存,当我们改变其中一个变量时,另一个也会变,如下:
a = [11,22,33]
b = a
a[0] = 123
print(a) # [123, 22, 33]
print(b) # [123, 22, 33]
在 Python 中还有深拷贝,它是重新开辟一块区域用来存储变量的,如下:
import copy a = [11, 22, 33]
b = a
c = [11, 22, 33]
d = copy.deepcopy(a)
print(a == b, a is b) # True True
print(a == c, a is c) # True False
print(a == d, a is d) # True False a[0] = 123
print(a) # [123, 22, 33]
print(b) # [123, 22, 33]
print(c) # [11, 22, 33]
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() 到底有什么区别呢,我们再看下面的代码:
import copy a = [11, 22, [123,456]]
b = copy.copy(a)
c = copy.deepcopy(a)
a[2][0] = 789
print(a) # [11, 22, [789, 456]]
print(b) # [11, 22, [789, 456]]
print(c) # [11, 22, [123, 456]]
从上面的输出结果可以看出,b 变量随 a 变量的变化而变化了,而 c 变量没有。
很显然这时 copy() 函数拷贝的值随着原对象的值修改了,而 deepcopy() 的值没有随着原对象的值修改。主要是因为 deepcopy() 会将复杂对象的每一层复制一个单独的个体出来对于 copy() 函数要慎用,慎用。
Python 从入门到进阶之路(七)的更多相关文章
- Python 从入门到进阶之路(一)
人生苦短,我用 Python. Python 无疑是目前最火的语言之一,在这里就不再夸他的 NB 之处了,本着对计算机编程的浓厚兴趣,便开始了对 Python 的自学之路,并记录下此学习记录的心酸历程 ...
- Python 从入门到进阶之路(六)
之前的文章我们简单介绍了一下 Python 的面向对象,本篇文章我们来看一下 Python 中异常处理. 我们在写程序时,有可能会出现程序报错,但是我们想绕过这个错误执行操作.即使我们的程序写的没问题 ...
- Python 从入门到进阶之路(五)
之前的文章我们简单介绍了一下 Python 的函数,本篇文章我们来看一下 Python 中的面向对象. Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是 ...
- Python 从入门到进阶之路(四)
之前的文章我们简单介绍了一下 Python 的几种变量类型,本篇文章我们来看一下 Python 中的函数. 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性, ...
- Python 从入门到进阶之路(三)
在之前的文章我们介绍了一下 Python 中 if while for 的使用,本章我们来看一下 Python 中的变量类型. 在 Python 定义变量时的规则是 变量名 = 变量 ,Python ...
- Python 从入门到进阶之路(二)
之前的文章我们对 Python 语法有了一个简单的认识,接下来我们对 Python 中的 if while for 做一下介绍. 上图为 if 判断语句的流程,无论任何语言,都会涉及到判断问题,if ...
- python快速入门及进阶
python快速入门及进阶 by 小强
- Python 爬虫从入门到进阶之路(七)
在之前的文章中我们一直用到的库是 urllib.request,该库已经包含了平常我们使用的大多数功能,但是它的 API 使用起来让人感觉不太好,而 Requests 自称 “HTTP for Hum ...
- Python 爬虫从入门到进阶之路(六)
在之前的文章中我们介绍了一下 opener 应用中的 ProxyHandler 处理器(代理设置),本篇文章我们再来看一下 opener 中的 Cookie 的使用. Cookie 是指某些网站服务器 ...
随机推荐
- springboot启动原理解析
springboot核心原理: 1.基于springmvc无配置文件完全注解化 + 内置web容器实现springboot框架.main函数方式的启动 2.通过maven快速整合第三方框架 sprin ...
- UWP 打开系统设置面板
由于UWP各种权限管理的比较严格,所以在执行某一个特殊的操作之前,最好先申请一下相应的权限,以便告知用户你使用了这个权限,而且可以有效的避免App崩溃. 比如你想让用户手动打开麦克风权限,那么可以执行 ...
- 全字段多条件搜索(api接口)
近期在做项目时遇到了一个全表全字段多条件搜索的需求,在平时搜索最常见的就是 字段+like +‘% 条件%’这种模式,但遇到多条件多字段时,这种就不适用了. 表字段已知,条件未知,条件数量未知,这种情 ...
- java读取地址数据文件
在工作中遇到读取地址文件数据: 1.读取本地文件数据(如:D:\data.txt) //适用于读取绝对地址文件 public String getData(String path) { String ...
- Scrum Meeting - 第七周【Alpha阶段】
每日任务内容: 本次会议为第七次Scrum Meeting会议 本次会议项目经理召开时间为20:00,在北区男生宿舍楼召开,召开时长约10分钟,探讨了本周选课网站编写的后续工作. 小组成员 本周任务 ...
- MySQL集群高可用
目录 MySQL高可用 Galera Cluster Galera Cluster Galera Cluster特点 Galera Cluster 缺点 Galera Cluster工作过程 Gale ...
- 针对base64编码和URIEncode的一点研究
Base64编码的作用 将任意的二进制比特串编码成由ASCii码中的64个可显示字符组成的字符串. 为什么需要base64编码? 所有的文件,本质上都是0.1组成的比特串,文本文件.二进制文件的区别只 ...
- 实战Netty集群
疯狂创客圈 Java 分布式聊天室[ 亿级流量]实战系列之 -25[ 博客园 总入口 ] 1.写在前面 1.1 实战Netty集群的理由 Java基础练习中,一个重要的实战练习是: java的聊天程序 ...
- java自学-常用api
API(Application Programming Interface),应用程序编程接口.Java API是JDK中提供给我们使用的类的说明文档.即jdk包里边写好的类,这些类将底层的代码实现封 ...
- SAP-BP 创建客商(摘抄)
FORM frm_bp02 . * 更改供应商所需变量 DATA:l_xfeld TYPE xfeld, "复选框 ls_data TYPE vmds_ei_main, "供应商总 ...