python复习--对象相关--对象生命周期

一. 一句话总览版

Python 对象的生命周期是:
创建 → 被引用 → 引用变化 → 不可达 → 回收

Python 只关心“引用”,不关心“是否使用”。

二、Python 世界里最重要的 3 个概念

1.对象(Object)

  • 真正存在于内存中的东西
  • 例如:整数、字符串、函数、类、列表……

2.名字(Name / 变量名)

  • 只是一个引用标签
  • 本身不存数据

3.引用(Reference)

  • 名字 / 容器 / 属性 → 对象 的指向关系
    名字 ──▶ 对象
    名字 ≠ 对象

三、对象生命周期第 1 阶段:创建(Creation)

  • 对象只会在执行“创建语句”时创建。

1. 常见的创建方式

绑定名字

x ──▶ <listobject>

名字 x 指向这个 list 对象
引用计数 = 1Python 不会“先创建一个没有引用的对象,再找名字给它”
这两步在语义上是原子完成的。

创建对象

[]

在内存中创建一个 list 对象
对象此时 必须被某个引用接住

逐字拆解 x = [] 到“解释器视角”

x =[]

在这一行里,发生了 两个动作(但对你来说像一步):

示例

a =10# 创建 int 对象 b =[]# 创建 list 对象 c ={}# 创建 dict 对象 d =lambda x: x # 创建函数对象

[] 是对象本身(一个 list 对象)
b 不是对象,只是一个名字(引用)
b = [] 的含义是:
创建一个 list 对象,然后让名字 b 指向它

2. def / class 也是“创建对象”

执行到这行时:
创建函数 / 类对象
绑定名字

语法创建的对象绑定的名字
def f()函数对象f
class A类对象A

示例

deff():passclassA:pass

四、对象生命周期第 2 阶段:被引用(Alive)

1.示例

  • 内存关系:f ──▶ <function f>
  • 此时:
    引用数 ≥ 1
    对象是“活着的”
    GC 不会碰它

示例

deff():pass

2.引用是怎么变化的?(这是核心)

引用 -1 的情况

b =None

a ───▶ []
引用数 = 1(对象仍活着)

引用 +1 的情况

a =[] b = a 

a ─┐
├──▶ []
b ─┘
引用数 = 2

五、对象生命周期第 3 阶段:不可达(Unreachable)

1. 关键规则

当一个对象没有任何引用指向它时,它就“不可达”

示例

f =[] f =None

执行过程:
f = []:创建 list,对象被 f 引用 (引用=1)
f = None:解除引用 (引用=0)执行结束后:
没有任何名字指向该 list
引用计数 = 0
对象不可达
等待 / 立即回收(CPython)

2. 补充(需要注意)

不可达 ≠ 立刻销毁(在所有实现中)

CPython:引用计数 → 通常立刻回收
其他实现(PyPy):可能延迟回收

六、对象生命周期第 4 阶段:回收(Garbage Collection)

  • Python 的 GC 两层机制

1. 第一层:引用计数(最核心、最常用)

  • CPython 中,每个对象都有 refcount,这是 CPython 的基础机制。

什么是引用计数?
每个对象内部都有一个 refcount
每多一个引用,计数 +1
每少一个引用,计数 -1
当 refcount == 0 → 对象立刻销毁(大多数情况)
示例:

a =[] a =None

a = [] → 引用数 = 1
a = None → 引用数 = 0 → 回收

2. 第二层:循环垃圾回收(Cycle GC)

  • 为了解决循环引用,Python 引入了第二层机制。

即使这样:

a =None b =None

你会以为对象可以被回收,但实际上:a 和 b 互相引用
各自的 refcount 都不为 0
引用计数机制 无法回收它们

循环引用问题(引用计数解决不了)

a =[] b =[] a.append(b) b.append(a)

此时结构是:

 a → b ↑ ↓ └───┘ 

循环 GC 的核心思想
只要对象组“从程序中不可达”,就应该被回收
不管它们内部怎么互相引用。

a =[] b =[] a.append(b) b.append(a) a =None b =None
  • 此时:
    程序中已经没有任何变量能访问这两个列表
    虽然它们内部还互相引用
    循环 GC 会发现它们不可达,并最终回收

3. 表格记忆

机制解决什么特点
引用计数普通对象回收快、实时
循环 GC循环引用定期扫描、补救机制

99% 情况靠引用计数
1% 循环引用靠 GC 扫描

七、一个“完整生命周期时间线”示例(重点)

1. 示例

defmake(): x =[]return x a = make() b = a a =None b =None

执行过程:

时刻状态
x = []创建 list,对象一出生就被 x 引用,引用数 = 1
return x返回引用,返回的是对象的引用,不是新对象
a = make()a 指向 list,引用数 = 1
b = a引用 +1
a = None引用 -1
b = None引用 -1,引用 = 0 → 回收

这里的 a 和 b 这两个名字,绑定到了同一个 list 对象上

八、装饰器中的对象生命周期

1. 示例一:装饰器保存原函数引用

defdecorator(func):defwrapper(): func()return wrapper @decoratordeff():print("hi")

装饰器在函数定义阶段执行,等价于:

deff():print("hi")defdecorator(func):defwrapper(): func()return wrapper f = decorator(f)

逐步执行过程(对象 + 引用)

  1. 原函数为什么没被回收?
    因为:
    wrapper.closure → func → f_original
    虽然名字 f 不再指向原函数
    但 wrapper 闭包仍然引用它
    f_original 仍然存活
    总结一句话, 装饰器通过闭包,延长了原函数对象的生命周期

返回 wrapper 并重新绑定名字

f = wrapper 

原来的 f 名字不再指向 f_original
f → wrapper

创建 wrapper 函数对象

defwrapper(): func()

创建 wrapper 函数对象
wrapper 闭包捕获了 func
func → f_original

调用装饰器

decorator(f_original)

func 参数 → 引用 f_original

创建原函数对象

deff():print("hi")

创建 函数对象 f_original
名字 f → 绑定到 f_original

2. 示例二:装饰器不保存原函数引用

defdecorator(func):returnlambda:print("hi")@decoratordeff():print("hi")

等价于:

deff():print("hi")defdecorator(func):returnlambda:print("hi") f = decorator(f)

执行过程

  1. 创建原函数对象创建 f_original
    f → f_original
  2. 结果
    f_original 变为不可达对象
    引用计数 = 0
    立即被回收

名字重新绑定

f = lambda_func 

原来的 f 不再指向 f_original
没有任何引用指向 f_original

调用 decorator

decorator(f_original)

但 返回的 lambda 没有引用 func

3. 两种装饰器的“生命周期对比表”

情况原函数是否被保存原函数生命周期
wrapper 使用 func是(闭包)存活
不使用 func立即回收

九、对象“不会被回收”的常见原因

1. 还有全局引用

cache =[] cache.append(obj)

2. 被闭包捕获

defouter(): x =[]definner():return x return inner 

3. 存在循环引用 + del

classA:def__del__(self):pass

可能导致无法回收

十、你现在可以用这段话“完美描述对象生命周期”

Python 对象在执行创建语句时生成,
通过名字、容器或属性被引用;
在运行过程中引用动态变化;
当对象不再被任何引用指向时变为不可达;
随后由引用计数或 GC 回收,生命周期结束。

这是解释器级理解

十一、最终总结(必记)

Python 不关心是否调用
Python 不预测未来代码
Python 只在当前时刻检查引用
对象一旦不可达,永远无法复活

Read more

Java 时间类(中):JDK8 全新时间 API 详细教程

Java 时间类(中):JDK8 全新时间 API 详细教程

🏠个人主页:黎雁 🎬作者简介:C/C++/JAVA后端开发学习者 ❄️个人专栏:C语言、数据结构(C语言)、EasyX、JAVA、游戏、规划、程序人生 ✨ 从来绝巘须孤往,万里同尘即玉京 文章目录 * Java 时间类(中):JDK8 全新时间 API 详细教程 🕘 * 📝 文章摘要 * 🧠 上篇知识回顾 * 一、JDK8 时间类整体架构 🏛 * 二、ZoneId 时区类 🌍 * 1. 核心作用 * 2. 常用方法 * 3. 代码示例 * 三、Instant 时间戳类 ⚡ * 1. 核心作用 * 2. 常用方法 * 3. 代码示例 * 四、ZonedDateTime

By Ne0inhk
Flutter 三方库 js_wrapping 的鸿蒙化适配指南 - 实现 Dart 与 JavaScript 的无缝对象包装、支持强类型回调与属性映射

Flutter 三方库 js_wrapping 的鸿蒙化适配指南 - 实现 Dart 与 JavaScript 的无缝对象包装、支持强类型回调与属性映射

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 js_wrapping 的鸿蒙化适配指南 - 实现 Dart 与 JavaScript 的无缝对象包装、支持强类型回调与属性映射 前言 在进行 Flutter for OpenHarmony 的 Web 混合开发时,频繁地在 Dart 层与底层 JavaScript 环境进行数据交互是不可避免的。虽然官方提供了基本的 dart:js,但在处理复杂的 JS 对象和回调时,代码往往会变得杂乱无章。js_wrapping 提供了一个更优雅的、类型安全的包装层。本文将指导大家如何在鸿蒙端利用该库提升 JS 互操作的开发体验。 一、原理解析 / 概念介绍 1.1 基础原理

By Ne0inhk
你以为你在部署 AI 助手,其实也可能在打开一扇“数据侧门”:OpenClaw 安全风险全解析

你以为你在部署 AI 助手,其实也可能在打开一扇“数据侧门”:OpenClaw 安全风险全解析

🔥 个人主页:杨利杰YJlio❄️ 个人专栏:《Sysinternals实战教程》《Windows PowerShell 实战》《WINDOWS教程》《IOS教程》《微信助手》《锤子助手》《Python》《Kali Linux》《那些年未解决的Windows疑难杂症》🌟 让复杂的事情更简单,让重复的工作自动化 你以为你在部署 AI 助手,其实也可能在打开一扇“数据侧门”:OpenClaw 安全风险全解析 * * 1、你以为你在装 AI 助手,其实你可能在给系统加一个“高权限自动化入口” * 2、OpenClaw 和普通 AI 最大的区别,到底在哪里? * 3、我为什么说:OpenClaw 更像“拿到部分权限的数字操作员”? * 4、为什么说 AI 助手不是“更聪明的搜索框”? * 5、OpenClaw 的 5

By Ne0inhk
字节跳动AI IDE:Trae 完全上手指南——从零安装到熟练使用,开启AI驱动开发新范式

字节跳动AI IDE:Trae 完全上手指南——从零安装到熟练使用,开启AI驱动开发新范式

目录 * 前言:当IDE进化为智能体 * 1.初识Trae * 1.1 Trae是什么? * 1.2 Trae的核心优势 * 1.3 谁适合使用Trae? * 2.安装与初始配置 * 2.1 支持的操作系统 * 2.2 下载与安装步骤 * 2.3 验证安装成功 * 3.界面导航(五分钟熟悉布局) * 3.1 核心区域功能说明 * 3.2 常用快捷键速查 * 4.核心AI功能详解 * 4.1 Chat模式:随时提问的编程助手 * 4.2 Builder模式:自然语言生成完整项目 * 4.2.1 实战案例:做一个待办事项应用 * 4.

By Ne0inhk