id() 和 is 比较的是对象在内存中的唯一地址,而非值相等;同一对象多次赋值变量,id() 不变,a is b 为 True 当且仅当二者指向同一内存地址。

Python 的 id() 和 is 到底在比什么
它比的不是“值相等”,而是对象在内存中的唯一地址。同一个对象,无论赋多少次变量,id() 都不变;两个变量指向同一块内存,a is b 才为 True。
常见错误现象:用 == 误判引用关系,或以为 list.append(x) 后 x 被“复制进去了”——其实只是存了对 x 的引用。
- 小整数(-5 到 256)和短字符串会被缓存,所以
a = 100; b = 100; a is b返回True,但这属于实现细节,不可依赖 - 自定义类实例、列表、字典等每次
new都生成新地址,哪怕内容完全一样 - 函数内返回局部列表,外部接收后仍指向原对象,修改会影响函数内“已结束”的上下文——因为没拷贝,只有引用
为什么 sys.getrefcount() 的结果总比预期多 1
调用 sys.getrefcount(obj) 这个动作本身,会让解释器临时持有一份引用(把 obj 压入 C 层参数栈),所以返回值恒为真实引用数 + 1。
使用场景有限:主要用于调试循环引用、确认对象是否被意外持有,不能靠它判断“变量是否还活着”。
立即学习“Python免费学习笔记(深入)”;
- 想测变量
x的引用数?得写成sys.getrefcount(x) - 1才接近真实值 - 传入字面量会触发临时对象创建,比如
sys.getrefcount(123)返回的不是你想象中那个“123”的计数,而是临时 int 对象的计数 - CPython 中,引用计数归零立即触发
__del__(如果定义了)和内存释放;但 PyPy、Jython 等不保证此行为
del 语句和变量赋值为 None 的区别在哪
del x 是从当前作用域的命名空间里彻底移除名字 x,而 x = None 是把 x 指向另一个对象(None),原对象引用数只减 1,未必释放。
Dbsite企业网站管理系统V1.5.0 秉承"大道至简 邦达天下"的设计理念,以灵巧、简单的架构模式构建本管理系统。可根据需求可配置多种类型数据库(当前压缩包支持Access).系统是对多年企业网站设计经验的总结。特别适合于中小型企业网站建设使用。压缩包内包含通用企业网站模板一套,可以用来了解系统标签和设计网站使用。QQ技术交流群:115197646 系统特点:1.数据与页
容易踩的坑:以为 x = None 就等于“清空”或“断开连接”,其实只要还有别的变量(比如类属性、闭包、全局字典里的键)指着它,对象就还在。
- 对大对象(如 pandas DataFrame、numpy array),
del x更干净,尤其在交互式环境反复加载时能防内存涨 -
del不影响其他同名变量(比如嵌套作用域里的x),它只删当前 scope 的绑定 - 若对象被循环引用(如 A 持有 B,B 又持有 A),即使所有外部变量都
del了,引用计数也不归零,得靠 gc 模块的周期性清理
什么时候引用计数不管用,必须靠 gc 模块
纯引用计数无法处理循环引用:A 引用 B,B 引用 A,外部再无其他引用,但两者引用计数都 ≥1,不会自动回收。
这是 CPython 的硬限制,不是 bug,是设计取舍。所有含 __del__ 方法的对象一旦卷入循环,就必须依赖 gc。
- 默认 gc 是开启的,但可被关闭(
gc.disable())——关掉后循环引用对象永不回收,内存只增不减 -
gc.collect()可手动触发,返回本次回收的对象数;调试时加gc.set_debug(gc.DEBUG_STATS)能看到每轮扫描详情 - 避免在
__del__里操作可能被 gc 管理的全局结构(如往 list.append),否则可能引发“对象已被销毁”的静默失败
引用计数是 Python 内存管理的基座,但它只解决“单向依赖”的释放问题;真正让复杂对象图安全落地的,是那层看不见的 gc 循环检测逻辑——而它恰恰不参与日常编码的显式控制,只在后台默默兜底。









