每天1分钟,轻松懂 Python
这是一份有基础、有深度的 Python 核心技术手册
对象比较:== vs is
1、核心区别
| 比较操作 | 含义 | 实现逻辑 |
|---|---|---|
== | 值相等 | 调用对象的 __eq__ 方法,遍历内容进行比较 |
is | 身份(ID)相同 | 直接比较对象的内存地址(id()函数值 ) |
2、小整数缓存
Python 对 -5~256 的整数,会进行缓存复用
a = 10
b = 10
print(a is b) # True(复用缓存,ID 相同)
id(a) # 输出:4374045552
id(b) # 输出:4374045552
a = 257
b = 257
print(a is b) # False(超出缓存,重新分配内存)
print(id(a)) # 4448081648
print(id(b)) # 4448084976
你是否也遇到过,当 a = 257,b = 257 ,a is b 输出 True 呢?
这里就需要介绍一下 python 编译器中的 “常量折叠” 优化。
“常量折叠” 是Python在编译阶段的优化,它会提前计算代码中由纯常量组成的表达式,并用计算结果替换掉整个表达式,从而减少运行时的计算开销。
试着想像一下,你和对象在饭店点菜,你要了“1果汁“,你对象也要了”1果汁”。这会儿,聪明的厨子会在准备时,就直接写成“2杯水”。那Python编译器就是这个“聪明的厨子”。
下面,我们用代码看看:
a = 257
b = 257
# 经过“常量折叠”优化后,相当于:
CONST_257 = 257 # 编译器内部创建一个常量257
a = CONST_257
b = CONST_257 # a和b指向同一个257对象
这就是为什么在脚本中 a is b 返回 True 的原因。
不同的环境下,“常量折叠” 优化也会有不同的表现。
在 脚本文件执行 和 交互式环境里多行一起粘贴 时,就会触发 “常量折叠” 优化。
那这会儿 `a is b` 就会返回 True。
在 交互式环境里逐行输入 时,就不会触发 “常量折叠” 优化。
那这会儿 `a is b` 就会返回 False。
3、性能与使用场景
is效率更高(直接比 ID,无需遍历内容 ),常用于判断None(if a is None)。==需递归比较内容,适合比较对象值的判断。
对象拷贝
1、浅拷贝
浅拷贝会重新分配一块内存,创建一个新的对象。但是,里面的嵌套的元素还是原对象的引用。
# 实现方式:list()、dict() 、切片([:] )、copy.copy()。
l1 = [1, [2, 3]]
l2 = list(l1) # 浅拷贝
l1 == l2 # True,它们的内容相同
l1 is l2 # False,它创建了一个新对象,所以内存地址不同
# 注意:若原来的嵌套对象可变,修改原来的嵌套对象时,就会影响到拷贝对象。
l1[1].append(4)
print(l1) # [1, [2, 3, 4]] 正常修改
print(l2) # [1, [2, 3, 4]] 被影响了
浅拷贝时,仅顶层对象重新分配内存,但 嵌套对象(如列表、字典)还是复制引用。
若原嵌套对象是可变的。修改原嵌套对象时,就会影响到拷贝对象。
2、深拷贝
是指重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中。
新对象和原对象没有任何关联。
# 使用 copy.deepcopy() 实现深拷贝
import copy
l1 = [1, [2, 3]]
l2 = copy.deepcopy(l1) # 深拷贝
l1[1].append(4)
print(l1) # [1, [2, 3, 4]] 正常修改
print(l2) # [1, [2, 3]] 拷贝对象不受影响
-------- 写在最后 --------
关注我,每天1分钟,轻松懂 Python
我的同名公众号正在连载《FastAPI 开发实战》、《Python 核心技术》、《职场》。
点赞 :如果觉得有收获,点赞支持一下吧!
分享 :分享给身边同样对Python感兴趣的朋友!
关注我 :不要错过每一篇 Python 实战内容!
#Python #FastAPI #API #Web开发 #程序员 #编程教程 #效率提升