Python 高级编程 019:类变量与实例变量彻底解析

Python 高级编程 019:类变量与实例变量彻底解析

在 Python 面向对象编程里,类变量实例变量是最基础、却最容易踩坑的知识点。很多时候代码逻辑异常、数据被意外篡改,根源都在于没分清:变量到底归属于「类」,还是归属于「实例」。

今天我们就用最通俗的语言 + 可直接运行的代码,把这两个概念掰开揉碎,让你彻底理解它们的定义、查找规则与修改行为。


一、先搞懂:什么是类变量?什么是实例变量?

1.1 类变量:归属于类的「共享资产」

类变量,直接定义在类内部、方法外部 ,它不属于某一个实例,而是整个类的所有实例共享的属性。

你可以把它理解为:这个类的「公共配置」「全局参数」。

python 复制代码
class A:
    # 🔥 类变量:定义在类内部、方法外
    AA = 1

    def __init__(self, x, y):
        self.x = x
        self.y = y

1.2 实例变量:归属于对象的「私有资产」

实例变量(对象变量),定义在方法内部 ,并且必须以 self. 开头绑定到具体实例。

它是每个对象独立拥有的属性,互不干扰。

python 复制代码
class A:
    AA = 1

    def __init__(self, x, y):
        # 🔥 实例变量:绑定到 self(当前实例)
        self.x = x
        self.y = y

一句话区分:

  • 直接写在类里 → 类变量

  • 带 self. → 实例变量


二、属性查找规则:先实例,后类 ⬆️

Python 查找属性有一条铁律

从当前实例自身找 → 找不到 → 向上找类的属性 → 还找不到 → 报错!

而反过来:类绝对不会向下查找实例的属性!

我们用代码验证:

python 复制代码
# 实例化对象
a = A(2, 3)

# 访问实例变量(自己就有,直接返回)
print(a.x)   # 2
print(a.y)   # 3

# 访问类变量(实例自己没有,向上找到类的 AA)
print(a.AA)  # 1

# ❌ 类不能访问实例变量!
# print(A.x) → 报错:type object 'A' has no attribute 'x'

这就是为什么:

  • 实例能读到类变量

  • 类绝对读不到实例变量

    因为实例变量是绑定到具体对象的,类根本不知道它有哪些实例。


三、最容易踩坑:修改行为完全不同!

这是 90% 开发者都会混淆的点:

用「类名」修改 vs 用「实例名」修改,结果天差地别!

3.1 用「类名」修改:真正改类变量

python 复制代码
class A:
    AA = 1
    def __init__(self, x, y):
        self.x = x
        self.y = y

a = A(2, 3)
# ✅ 用类名修改:真正修改类变量
A.AA = 11

print(a.AA)    # 11(实例共享到新值)
print(A.AA)    # 11(类本身已被修改)

✅ 结论:

类变量一改,所有实例全部同步更新!

3.2 用「实例名」赋值:不是修改,是「新建」!

python 复制代码
class A:
    AA = 1
    def __init__(self, x, y):
        self.x = x
        self.y = y

a = A(2, 3)
# ❌ 看起来像修改,实际是:给实例 a 新建一个实例变量 AA
a.AA = 100

print(a.AA)    # 100(实例自己有了,优先用自己的)
print(A.AA)    # 1(类变量纹丝不动!)

🔥 核心真相:

实例。属性 = 值 → 不会修改类变量,而是给这个实例新增一个同名实例变量!

从此:

  • 实例 a 有自己的 AA

  • A 依然保留原来的 AA

    两者完全独立,互不影响。


四、类变量的本质:所有实例「共享」

再看一个例子,你会更通透:

python 复制代码
class A:
    AA = 1
    def __init__(self, x, y):
        self.x = x
        self.y = y

# 实例化两个对象
a = A(2, 3)
b = A(4, 5)

# 统一修改类变量
A.AA = 11

print(a.AA)  # 11
print(b.AA)  # 11
print(A.AA)  # 11

✅ 最终结论:

类变量是全局共享的,一个修改,全部生效;
实例变量是独立私有的,各用各的,互不干扰。


五、一张表总结,再也不会忘

维度 类变量 实例变量
定义位置 类内部、方法外 方法内部,带 self.
归属 整个类,所有实例共享 单个实例,独立私有
查找顺序 实例找不到时向上查找 优先查找自身
修改方式 类名。属性 = 值 实例名。属性 = 值
实例赋值 不会改类,会新建实例属性 直接修改自身属性
影响范围 所有实例同步生效 只影响当前实例

六、最后小结 ✨

在 Python 面向对象的世界里:

  • 类变量是「公共池」,大家共用,一改全改;

  • 实例变量是「私人抽屉」,各自独立,互不打扰。

只要记住两条铁律:

  1. 查找:先实例,后类

  2. 赋值:实例赋值 = 新建属性,不是修改类变量

你就彻底掌握了类变量与实例变量的核心,后续再学习属性查找顺序、自省机制,都会一通百通。

下一篇我们继续深入:Python 属性查找的完整链路(MRO 与实例 / 类 / 父类优先级),带你彻底打通面向对象任督二脉!

相关推荐
小九九的爸爸1 小时前
前端想要入门Agent开发,要具备哪些Python基础?
python·agent·ai编程
阿耶同学2 小时前
手把手教你用 LangGraph 搭建三层嵌套 Agent 架构
python·程序员
花酒锄作田18 小时前
Pydantic校验配置文件
python
hboot18 小时前
AI工程师第四课 - 深度学习入门
pytorch·python·神经网络
ZhengEnCi1 天前
P2M-Matplotlib折线图完全指南-从数据可视化到趋势分析的Python绘图利器
python·matlab·数据可视化
ZhengEnCi1 天前
P2L-Matplotlib饼图完全指南-从数据可视化到图表定制的Python绘图利器
python·matlab
曲幽1 天前
你的REST接口还在“过度投喂”数据吗?——FastAPI + GraphQL实战避坑指南
python·fastapi·web·graphql·route·cors·rest·strawberry
用户8358086187911 天前
基于 Self-RAG 与列表级重排序的进阶 RAG 系统设计与实现
python
Warson_L2 天前
Python `Annotated` 与 LangGraph Reducer 学习笔记
python
韩师傅2 天前
海天线算法的前世今生
python·计算机视觉