1 分钟读懂:Python 中的对象比较和对象拷贝

26 阅读4分钟

202512311556269341

每天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 = 257b = 257a 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,无需遍历内容 ),常用于判断 Noneif 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开发 #程序员 #编程教程 #效率提升