Python:类变量 vs 全局变量 --- 生命周期区别
核心一句话: 全局变量依附模块;类变量依附类对象。谁的宿主活着,变量就活着;宿主被 GC 回收,变量跟着销毁。
一、全局变量
全局变量定义在模块顶层,保存在模块对象的 __dict__。
- 创建时机 模块被第一次导入(
import)的时候,执行模块代码,创建全局变量。 - 存活期间 模块一旦导入成功,模块对象会一直驻留内存 ,放到
sys.modules缓存。 只要进程没结束,模块就不会被回收;全局变量一直存在。 即使你不再使用模块里的函数,模块对象依然在sys.modules,全局变量保留。 - 销毁时机
- 正常情况:程序进程退出时才销毁
- 极少数场景:手动从
sys.modules删除模块引用 + 无任何其他引用,才会 GC 回收模块,全局变量随之释放(实际开发极少这么做)
特点:生命周期很长,几乎贯穿整个程序运行期。
二、类变量
类变量写在class内部、方法之外,保存在类对象的 __dict__。
-
创建时机 执行
class定义语句那一刻,Python 会创建类对象,同时生成类变量。class A: x = 10 # 执行class这一行,就创建类变量x -
存活期间 只要类对象还有引用 ,类变量就存在。 引用来源可以是:
- 类名本身
A - 类的实例
- 其他地方保存的类引用
- 类名本身
-
销毁时机 当类对象所有引用全部消失 ,GC 把类对象回收,类变量跟着一起销毁。
- 如果这个类一直被引用(比如全局作用域定义的类),类变量就和全局变量一样活到程序结束;
- 如果函数内部动态定义 class,函数执行完没有外部引用,类对象就会被 GC,类变量直接释放。
示例:
def create_class():
class Temp:
val = 99
return Temp()
obj = create_class()
# 只要obj还在,Temp类对象就存在,Temp.val类变量存活
del obj
# obj删除后,如果没有任何地方引用Temp类,类对象被GC,val销毁
三、关键差异点
- 宿主不同
- 全局变量:宿主是模块对象,模块一旦缓存进 sys.modules 很难回收。
- 类变量:宿主是类对象,类对象满足无引用条件就可以 GC。
- 生命周期灵活性
- 全局变量:一旦导入,基本常驻内存,很难主动释放。
- 类变量:可以随类对象销毁而释放。动态创建的类,用完即可回收,内存可以释放。
- 定义位置带来的常见现象 很多类写在模块顶层,这时类对象本身就是全局的,类变量也会活到程序结束,看起来生命周期和全局变量一样。
这是很多人容易混淆的点:不是类变量天生短命,是看类对象的引用是否还存在。
-
实例删除,不影响类变量 就算所有实例全部 del,只要类本身还在,类变量依然存活。
class A:
x = 1
a1 = A()
del a1
print(A.x) # 仍然存在,类对象A还在
四、对比表
表格
| 项目 | 全局变量 | 类变量 |
|---|---|---|
| 归属宿主 | 模块对象 | 类对象 |
| 创建时机 | 模块第一次 import,执行模块代码 | 执行class定义语句时创建 |
| 销毁条件 | 模块从 sys.modules 移除 + 无引用;一般进程结束销毁 | 类对象全部引用消失,GC 回收类对象,类变量销毁 |
| 是否可主动回收 | 很难,模块会被 sys.modules 缓存 | 可以,解除类的所有引用即可被 GC |
| 实例删除影响 | 无关 | 删除实例,只要类还在,类变量不变 |
| 典型生命周期 | 几乎贯穿整个程序 | 可长可短;顶层定义类则常驻,动态类用完可回收 |
五、简单总结
- 模块顶层定义的全局变量:程序启动导入后一直存活,直到程序退出。
- 类变量的生命周期绑定类对象 :
- 类在模块顶层定义 → 类常驻,类变量常驻;
- 动态创建局部类 → 引用消失,mp.ma-xy.com/blog/9kLm2QpX7a.html
mp.ma-xy.com/blog/Zx4Tn8Vr1B.html
mp.ma-xy.com/blog/Qw7Yh3Ns5D.html
mp.ma-xy.com/blog/Mc2Jv9Kp6E.html
mp.ma-xy.com/blog/Rt8Bn4Xz0F.html
mp.ma-xy.com/blog/Hg5Lp1Wq7G.html
mp.ma-xy.com/blog/Uv3Dm6Yr2H.html
mp.ma-xy.com/blog/Pa9Kc4Nt8J.html
mp.ma-xy.com/blog/Se2Qx7Vb5K.html
mp.ma-xy.com/blog/Fn6Wm1Zp3L.html
mp.ma-xy.com/blog/Yd4Hr9Cv2M.html
mp.ma-xy.com/blog/Jk7Tq3Bs8N.html
mp.ma-xy.com/blog/Ol1Pm5Xw6P.html
mp.ma-xy.com/blog/Bg8Nc2Vr4Q.html
mp.ma-xy.com/blog/Xm5Kt7Yd1R.html
mp.ma-xy.com/blog/Cv9Qp3Ln6S.html
mp.ma-xy.com/blog/Zr2Wm8Hx4T.html
mp.ma-xy.com/blog/Nk6Jd1Vp9U.html
mp.ma-xy.com/blog/Lq4Yt7Bc2V.html
mp.ma-xy.com/blog/Wp8Rm3Nx5W.html
mp.ma-xy.com/blog/Td1Kv6Qs9X.html
mp.ma-xy.com/blog/Hx5Pm2Zr7Y.html
mp.ma-xy.com/blog/Gc9Bn4Wt1Z.html
mp.ma-xy.com/blog/Vr3Lq8Jd6A.html
mp.ma-xy.com/blog/Mp7Yx2Kc5B.html
mp.ma-xy.com/blog/Ks4Wm9Nv3C.html
mp.ma-xy.com/blog/Qn1Rt6Bp8D.html
mp.ma-xy.com/blog/Dz5Jv2Xm7E.html
mp.ma-xy.com/blog/Sb9Lq4Hr1F.html
mp.ma-xy.com/blog/Yt3Pm8Kx6G.html
mp.ma-xy.com/blog/Rc7Wn1Vd4H.html
mp.ma-xy.com/blog/Bp2Qx9Lm5J.html
mp.ma-xy.com/blog/Nv6Tr3Yc8K.html
mp.ma-xy.com/blog/Lm1Jd7Wp2L.html
mp.ma-xy.com/blog/Xq5Kv9Bn4M.html
mp.ma-xy.com/blog/Ct8Rm2Hx7N.html
mp.ma-xy.com/blog/Zp3Yq6Ld1P.html
mp.ma-xy.com/blog/Gv9Wm4Nc5Q.html
mp.ma-xy.com/blog/Hk2Jx7Rt8R.html
mp.ma-xy.com/blog/Md6Pq1Bv3S.html
mp.ma-xy.com/blog/Tn8Lm5Wx2T.html
mp.ma-xy.com/blog/Qr4Yp9Kc7U.html
mp.ma-xy.com/blog/Vx1Jv6Nd3V.html
mp.ma-xy.com/blog/Kp7Wm2Ht9W.html
mp.ma-xy.com/blog/Bc5Rq8Lx4X.html
mp.ma-xy.com/blog/Nm9Yd3Pv1Y.html
mp.ma-xy.com/blog/Lt2Kx7Bc6Z.html
mp.ma-xy.com/blog/Xv8Qm4Nr5A.html
mp.ma-xy.com/blog/Cp1Jd9Wt3B.html
mp.ma-xy.com/blog/Zk6Lq2Yx8C.html
mp.ma-xy.com/blog/Gr3Pm7Vc1D.html
mp.ma-xy.com/blog/Hx9Bn5Kd4E.html
mp.ma-xy.com/blog/Mv2Tq8Lm6F.html
mp.ma-xy.com/blog/Tc7Yp1Rx3G.html
mp.ma-xy.com/blog/Qm4Jv9Wd5H.html
mp.ma-xy.com/blog/Vp8Km2Nx7J.html
mp.ma-xy.com/blog/Kd1Lq6Bt9K.html
mp.ma-xy.com/blog/Bx5Rm3Yc2L.html
mp.ma-xy.com/blog/Nq9Pv7Hd4M.html
mp.ma-xy.com/blog/Lm3Jx1Wt6N.html
mp.ma-xy.com/blog/Xc8Qm5Bv2P.html
mp.ma-xy.com/blog/Cv4Kd9Nr7Q.html
mp.ma-xy.com/blog/Zp1Yq6Lx3R.html
mp.ma-xy.com/blog/Gt7Wm2Vc9S.html
mp.ma-xy.com/blog/Hk5Jv8Rd1T.html
mp.ma-xy.com/blog/Mx9Pq3Bn6U.html
mp.ma-xy.com/blog/Tm2Ld7Wv4V.html
mp.ma-xy.com/blog/Qc6Yp1Kx8W.html
mp.ma-xy.com/blog/Vr3Jm9Nt5X.html
mp.ma-xy.com/blog/Kp8Qv4Bd2Y.html
mp.ma-xy.com/blog/Bm1Lx6Wc7Z.html
mp.ma-xy.com/blog/Nv5Rd9Yp3A.html
mp.ma-xy.com/blog/Lq2Km7Jx8B.html
mp.ma-xy.com/blog/Xt9Pm4Vc1C.html
mp.ma-xy.com/blog/Cd3Qv8Bn6D.html
mp.ma-xy.com/blog/Zx7Lp2Yr5E.html
mp.ma-xy.com/blog/Gm1Jd6Wv9F.html
mp.ma-xy.com/blog/Hv4Kq9Nx2G.html
mp.ma-xy.com/blog/Mp8Rm3Bc7H.html
mp.ma-xy.com/blog/Tq1Yv5Ld4J.html
mp.ma-xy.com/blog/Qx6Jm2Wt9K.html
mp.ma-xy.com/blog/Vc3Pq7Rn1L.html
mp.ma-xy.com/blog/Km9Ld4Bv6M.html
mp.ma-xy.com/blog/Bp2Xv8Yc3N.html
mp.ma-xy.com/blog/Nr5Qm1Jx7P.html
mp.ma-xy.com/blog/Lv8Kd3Wt2Q.html
mp.ma-xy.com/blog/Xm4Pq9Bc6R.html
mp.ma-xy.com/blog/Ct1Rv7Lx5S.html
mp.ma-xy.com/blog/Zp8Jm2Yd4T.html
mp.ma-xy.com/blog/Gq3Kv6Nx9U.html
mp.ma-xy.com/blog/Hm7Ld1Wc5V.html
mp.ma-xy.com/blog/Mv4Pq8Bt2W.html
mp.ma-xy.com/blog/Tr9Ym3Jx6X.html
mp.ma-xy.com/blog/Qc2Kv7Ld1Y.html
mp.ma-xy.com/blog/Vp6Rm4Nc8Z.html
mp.ma-xy.com/blog/Kx1Jd9Wv3A.html
mp.ma-xy.com/blog/Bm5Qq2Yt7B.html
mp.ma-xy.com/blog/Nc8Lm4Hx1C.html
mp.ma-xy.com/blog/Lv3Pq9Rd6D.html
mp.ma-xy.com/blog/Xt7Km2Bc5E.html类连同类变量一起被 GC 回收。
如果你想,我可以用代码配合gc模块演示,看类对象什么时候被垃圾回收。