类变量和实例变量的生命周期核心差异在于归属主体的创建 / 销毁时机:类变量随 “类” 的加载而生、随 “类” 的销毁而灭;实例变量随 “实例” 的创建而生、随 “实例” 的回收而灭。下面结合 Python 内存管理机制,分维度讲透生命周期,并附实操例子验证。
一、类变量的生命周期(类级生命周期)
类变量是类对象的属性,其生命周期完全绑定到 “类” 本身,而非类的实例。
1. 诞生时机:类定义被解释器执行时
当 Python 解释器执行到class 类名:代码块时,会先创建该类的 “类对象”(存储在内存的类命名空间中),同时初始化类变量并绑定到这个类对象上 —— 此时还未创建任何实例,类变量就已存在。
2. 存活阶段:类对象存在的整个周期
类变量创建后,只要类对象未被销毁,就一直存在于内存中:
- 可通过
类名.类变量全局访问 / 修改(哪怕没有任何实例); - 所有后续创建的实例,都能共享这个类变量(本质是实例从类对象中 “读取” 该属性);
- 即使所有实例都被销毁,类变量依然存在(因为它属于类,而非实例)。
3. 销毁时机:类对象被垃圾回收 / 程序结束时
类变量的销毁分两种场景:
- 正常场景:Python 程序运行结束时,解释器回收所有内存,类对象被销毁,类变量随之消失;
- 特殊场景:主动删除类对象(如
del 类名),或类对象失去所有引用(如在函数内定义的类,函数执行完后无外部引用),触发垃圾回收(GC),类变量被销毁。
类变量生命周期示例
python
运行
# 验证:类定义执行时,类变量已创建(无实例也能访问) class Student: school = "北京大学" # 类定义执行时,类变量诞生 # 无任何实例,仍能访问类变量(证明类变量已存在) print(Student.school) # 输出:北京大学 # 创建实例后,共享类变量 stu1 = Student() print(stu1.school) # 输出:北京大学 # 销毁所有实例(stu1被回收) del stu1 # 实例已销毁,但类变量仍存在 print(Student.school) # 输出:北京大学(类变量未随实例销毁) # 主动销毁类对象(触发类变量销毁) del Student # print(Student.school) # 报错:NameError: name 'Student' is not defined(类变量已消失)二、实例变量的生命周期(实例级生命周期)
实例变量是实例对象的属性,其生命周期完全绑定到 “实例” 本身,与类无关。
1. 诞生时机:实例被创建(__init__执行时)
当执行实例名 = 类名()时,Python 会先创建空的实例对象,再调用类的__init__方法初始化实例 —— 实例变量(self.变量名)在__init__方法执行时被赋值,正式绑定到该实例对象上,此时实例变量才诞生。
2. 存活阶段:实例对象存在的整个周期
实例变量创建后,仅在所属实例的生命周期内存在:
- 只能通过
实例名.实例变量访问(类名无法直接访问,因为它不属于类); - 每个实例的实例变量相互独立(A 实例的变量修改,不影响 B 实例);
- 实例变量的存活与类无关(哪怕类还存在,只要实例被销毁,其变量就消失)。
3. 销毁时机:实例对象被垃圾回收时
实例变量随实例的销毁而销毁,触发实例销毁的场景包括:
- 实例对象失去所有引用(如
del 实例名、实例变量被重新赋值); - 实例超出作用域(如函数内创建的实例,函数执行完后无外部引用);
- 程序结束时,所有实例被批量回收。
Python 的垃圾回收机制会自动检测 “无引用的实例对象”,并回收其内存,实例变量也随之被销毁。
实例变量生命周期示例
python
运行
class Student: def __init__(self, name): self.name = name # 实例创建时,实例变量name诞生 # 1. 创建实例 → 实例变量诞生 stu1 = Student("张三") print(stu1.name) # 输出:张三(实例变量存在) # 2. 销毁实例 → 实例变量消失 del stu1 # 解除stu1对实例对象的引用,实例被GC回收 # print(stu1.name) # 报错:NameError: name 'stu1' is not defined # 验证:不同实例的变量独立,生命周期互不影响 stu2 = Student("李四") stu3 = Student("王五") print(stu2.name) # 输出:李四 del stu3 # 销毁stu3,仅stu3的name消失 print(stu2.name) # 输出:李四(stu2的实例变量不受影响)三、生命周期核心对比表
| 维度 | 类变量 | 实例变量 |
|---|---|---|
| 诞生时机 | 类定义被解释器执行时(无实例也存在) | 实例创建时(__init__执行时) |
| 存活依赖 | 依赖类对象的存在 | 依赖所属实例对象的存在 |
| 销毁触发条件 | 类对象被回收 / 程序结束 | 实例对象被回收(无引用)/ 程序结束 |
| 与实例的关系 | 不依赖实例(实例销毁,类变量仍在) | 完全依赖实例(实例销毁,变量消失) |
| 作用范围 | 全局(类存在则可访问) | 仅所属实例(实例内可访问) |
四、关键补充:容易混淆的细节
“实例遮蔽类变量” 不影响类变量生命周期当执行
实例名.类变量名 = 新值时,本质是给实例新增一个同名实例变量,这个实例变量的生命周期遵循 “实例级规则”,但原类变量的生命周期不受影响(仍随类存在)。python
运行
class Student: school = "北大" # 类变量(生命周期绑定类) stu = Student() stu.school = "复旦" # 新增实例变量school(生命周期绑定stu) del stu # 实例变量school被销毁 print(Student.school) # 类变量仍存在,输出:北大类变量的 “修改” 不改变生命周期无论是通过
类名.类变量 = 新值修改类变量,还是通过self.__class__.类变量修改,都只是改变类变量的值,不会改变其生命周期(依然随类的创建 / 销毁而变化)。模块级类 vs 函数内类的生命周期差异
- 模块级定义的类:程序运行期间始终存在,类变量直到程序结束才销毁;
- 函数内定义的类:函数执行时创建类对象,函数执行完后若类无外部引用,类对象被回收,类变量随之销毁。
总结
- 类变量:“生” 在类定义执行时,“活” 在类存在的全周期,“死” 在类被回收 / 程序结束时(与实例无关);
- 实例变量:“生” 在实例创建(
__init__执行)时,“活” 在实例存在的周期,“死” 在实例被回收时(与类无关)。
一句话记:类变量跟类走,实例变量跟实例走。