类变量和全局变量的生命周期有什么区别?

Python:类变量 vs 全局变量 --- 生命周期区别

核心一句话: 全局变量依附模块;类变量依附类对象。谁的宿主活着,变量就活着;宿主被 GC 回收,变量跟着销毁。

一、全局变量

全局变量定义在模块顶层,保存在模块对象的 __dict__。

  1. 创建时机 模块被第一次导入(import)的时候,执行模块代码,创建全局变量。
  2. 存活期间 模块一旦导入成功,模块对象会一直驻留内存 ,放到 sys.modules 缓存。 只要进程没结束,模块就不会被回收;全局变量一直存在。 即使你不再使用模块里的函数,模块对象依然在 sys.modules,全局变量保留。
  3. 销毁时机
    • 正常情况:程序进程退出时才销毁
    • 极少数场景:手动从sys.modules删除模块引用 + 无任何其他引用,才会 GC 回收模块,全局变量随之释放(实际开发极少这么做)

特点:生命周期很长,几乎贯穿整个程序运行期。

二、类变量

类变量写在class内部、方法之外,保存在类对象的 __dict__。

  1. 创建时机 执行 class 定义语句那一刻,Python 会创建类对象,同时生成类变量。

    复制代码
    class A:
        x = 10   # 执行class这一行,就创建类变量x
  2. 存活期间 只要类对象还有引用 ,类变量就存在。 引用来源可以是:

    • 类名本身 A
    • 类的实例
    • 其他地方保存的类引用
  3. 销毁时机 当类对象所有引用全部消失 ,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销毁

三、关键差异点

  1. 宿主不同
  • 全局变量:宿主是模块对象,模块一旦缓存进 sys.modules 很难回收。
  • 类变量:宿主是类对象,类对象满足无引用条件就可以 GC。
  1. 生命周期灵活性
  • 全局变量:一旦导入,基本常驻内存,很难主动释放。
  • 类变量:可以随类对象销毁而释放。动态创建的类,用完即可回收,内存可以释放。
  1. 定义位置带来的常见现象 很多类写在模块顶层,这时类对象本身就是全局的,类变量也会活到程序结束,看起来生命周期和全局变量一样。

这是很多人容易混淆的点:不是类变量天生短命,是看类对象的引用是否还存在。

  1. 实例删除,不影响类变量 就算所有实例全部 del,只要类本身还在,类变量依然存活。

    class A:
    x = 1
    a1 = A()
    del a1
    print(A.x) # 仍然存在,类对象A还在

四、对比表

表格

项目 全局变量 类变量
归属宿主 模块对象 类对象
创建时机 模块第一次 import,执行模块代码 执行class定义语句时创建
销毁条件 模块从 sys.modules 移除 + 无引用;一般进程结束销毁 类对象全部引用消失,GC 回收类对象,类变量销毁
是否可主动回收 很难,模块会被 sys.modules 缓存 可以,解除类的所有引用即可被 GC
实例删除影响 无关 删除实例,只要类还在,类变量不变
典型生命周期 几乎贯穿整个程序 可长可短;顶层定义类则常驻,动态类用完可回收

五、简单总结

  1. 模块顶层定义的全局变量:程序启动导入后一直存活,直到程序退出。
  2. 类变量的生命周期绑定类对象 :

如果你想,我可以用代码配合gc模块演示,看类对象什么时候被垃圾回收。

相关推荐
Ai-_Man8 分钟前
Meta Muse还是不可以导出左侧所有对话,只能点进去单条内容导出,方法不对吗?
开发语言·人工智能·ai·小程序·c#·1024程序员节
梓豪csd11 分钟前
消息订阅中心:谁该收到哪条通知
java·开发语言·人工智能·低代码·自动化·1024程序员节
秋饼12 分钟前
Spring AI 2.1 Message Parts 深度实战:推理签名回放与跨轮记忆持久化的源码级落地
java·ai·技术分享·后端开发
学逆向的42 分钟前
C 枚举变量
c语言·开发语言·网络安全
Sakura_j_h_1 小时前
Python 在定时任务里输出 emoji,UnicodeEncodeError 从哪来
开发语言·字符编码·windows·python·定时任务
thefool1122661 小时前
TCP 1
java·1024程序员节
金銀銅鐵3 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(下)
java·后端·ai编程
AI人工智能+电脑小能手4 小时前
一次请求打几个下游,这个Java并行任务工具类6个方法按序聚合
java·线程池·并发编程·1024程序员节·批量处理·并行任务
paopaokaka_luck5 小时前
心理咨询管理系统(WebSocket实时沟通、基于用户的协同过滤、 ECharts多维分析、 预约业务流程、预约校验与定时处理)
java·vue.js·spring boot·mysql·spring·echarts·1024程序员节
2301_32241428046 小时前
springboot农产品交易平台的设计与实现08055-计算机毕设 原创(免费领源码+部署教程+开发环境)
java·spring boot·redis·mysql·tomcat·maven·mybatis