在 Python 类中,变量主要分为两大类:类变量 和 实例变量,理解它们的区别是掌握 Python 面向对象编程的关键。

类变量
类变量是属于类本身的变量,而不是属于类的某个特定实例,这意味着所有该类的实例都共享同一个类变量,当你修改类变量时,这个修改会影响到所有实例。
如何定义
类变量通常在类定义的顶部,但在任何方法(__init__ 或其他)之外定义。
特点
- 共享性:所有实例共享同一个值。
- 定义位置:在类内部,方法之外。
- 访问方式:可以通过
类名.变量名或实例名.变量名访问。
示例
class Dog:
# 这是一个类变量
species = "Canis familiaris" # 所有狗都属于这个物种
def __init__(self, name, age):
# name 和 age 是实例变量,每个实例都有自己独立的副本
self.name = name
self.age = age
# --- 使用 ---
# 创建两个 Dog 实例
dog1 = Dog("Buddy", 5)
dog2 = Dog("Milo", 3)
# 访问类变量
print(f"{dog1.name} is a {dog1.species}.") # 输出: Buddy is a Canis familiaris.
print(f"{dog2.name} is a {dog2.species}.") # 输出: Milo is a Canis familiaris.
# 通过类名访问类变量
print(f"The species of all dogs is: {Dog.species}") # 输出: The species of all dogs is: Canis familiaris
# 修改类变量
# 注意:这会影响到所有实例
Dog.species = "Canis lupus" # 假设我们改成了狼
print(f"{dog1.name} is now a {dog1.species}.") # 输出: Buddy is now a Canis lupus.
print(f"{dog2.name} is now a {dog2.species}.") # 输出: Milo is now a Canis lupus.
⚠️ 潜在的陷阱
当你通过实例去修改一个类变量时,Python 的行为可能会让你感到意外,它不会修改类本身,而是在该实例上创建一个新的实例变量,屏蔽了类变量。
class Cat:
species = "Felis catus"
kitty = Cat()
print(f"Initial species via class: {Cat.species}") # 输出: Felis catus
print(f"Initial species via instance: {kitty.species}") # 输出: Felis catus
# 通过实例修改 species
kitty.species = "Panthera pardus" # 假设我们改成了豹猫
# 现在看看发生了什么
print(f"Species via instance after change: {kitty.species}") # 输出: Panthera pardus (这是实例变量)
print(f"Species via class after change: {Cat.species}") # 输出: Felis catus (类变量没有被修改)
# 创建另一个实例
another_cat = Cat()
print(f"Species of another cat: {another_cat.species}") # 输出: Felis catus (它仍然是原来的类变量)
实例变量
实例变量是属于类的实例的变量,每个实例都拥有自己的一套实例变量,它们之间互不影响。

如何定义
实例变量通常在 __init__ 构造方法中,通过 self 关键字来定义。self 代表类的实例本身。
特点
- 独立性:每个实例都有自己独立的副本。
- 定义位置:通常在
__init__方法中,通过self.变量名定义。 - 访问方式:只能通过
实例名.变量名访问。
示例
class Car:
# 类变量,用于所有汽车
wheels = 4
def __init__(self, brand, model, color):
# 实例变量,每个汽车实例都有自己独立的 brand, model, color
self.brand = brand
self.model = model
self.color = color
# 每个实例也可以有自己的独立计数器
self.mileage = 0
# --- 使用 ---
car1 = Car("Toyota", "Camry", "Blue")
car2 = Car("Honda", "Civic", "Red")
# 访问实例变量
print(f"Car 1: {car1.brand} {car1.model}, Color: {car1.color}")
# 输出: Car 1: Toyota Camry, Color: Blue
print(f"Car 2: {car2.brand} {car2.model}, Color: {car2.color}")
# 输出: Car 2: Honda Civic, Color: Red
# 修改 car1 的实例变量,不会影响 car2
car1.color = "Black"
print(f"Car 1's new color: {car1.color}") # 输出: Car 1's new color: Black
print(f"Car 2's color is still: {car2.color}") # 输出: Car 2's color is still: Red
# 修改 car1 的里程数
car1.mileage += 100
print(f"Car 1's mileage: {car1.mileage}") # 输出: Car 1's mileage: 100
print(f"Car 2's mileage: {car2.mileage}") # 输出: Car 2's mileage: 0
其他类型的变量(了解即可)
除了类变量和实例变量,你还会在 Python 中遇到以下两种特殊的“变量”形式,它们在概念上与变量相关,但实现方式不同。
1 实例方法中的局部变量
这些变量定义在方法内部,只在该方法执行期间存在,方法执行完毕后就会被销毁,它们与类和实例无关。
class Calculator:
def add(self, a, b):
# result 是一个局部变量
result = a + b
return result
calc = Calculator()
total = calc.add(10, 5)
print(total) # 输出: 15
# 在这里无法访问 result,因为它只在 add 方法内有效
# print(result) # NameError: name 'result' is not defined
2 @property - 将方法伪装成属性
这是一种高级用法,当你不希望直接暴露实例变量,而是想通过一个“受控”的方式来访问或修改它时使用,它定义的方法看起来像一个属性,但可以在访问时执行额外的逻辑。

class BankAccount:
def __init__(self, balance):
# 使用一个下划线开头的变量名来暗示这是一个“受保护的”内部变量
self._balance = balance
@property
def balance(self):
"""这是一个属性访问器,用于获取余额"""
print("Getting balance...")
return self._balance
@balance.setter
def balance(self, new_balance):
"""这是一个属性设置器,用于设置余额"""
print("Setting balance...")
if new_balance < 0:
print("Error: Balance cannot be negative.")
else:
self._balance = new_balance
# --- 使用 ---
account = BankAccount(1000)
# 像访问属性一样调用方法,而不是用括号
print(f"Your balance is: {account.balance}")
# 输出:
# Getting balance...
# Your balance is: 1000
# 像修改属性一样调用方法
account.balance = 1500
print(f"Your new balance is: {account.balance}")
# 输出:
# Setting balance...
# Getting balance...
# Your new balance is: 1500
# 尝试设置负值
account.balance = -500
# 输出:
# Setting balance...
# Error: Balance cannot be negative.
print(f"Your balance is still: {account.balance}")
# 输出:
# Getting balance...
# Your balance is still: 1500
总结与最佳实践
| 特性 | 类变量 | 实例变量 |
|---|---|---|
| 归属 | 属于类本身 | 属于类的实例 |
| 共享性 | 所有实例共享 | 每个实例独立拥有 |
| 定义位置 | 类内,方法外 | 通常在 __init__ 方法中,用 self 定义 |
| 内存占用 | 只有一份 | 每个实例都有一份 |
| 修改影响 | 修改会影响所有实例 | 修改只影响当前实例 |
| 用途 | 存储所有实例共享的数据,如物种、分类名等 | 存储每个实例特有的数据,如姓名、年龄、颜色等 |
何时使用哪种变量?
- 使用类变量:
当
