1. 实例变量 (self.xx
)
定义与作用:
- 实例变量是通过
self
关键字来定义的,通常在__init__
方法中进行初始化。 - 它们是绑定到对象实例的属性,每个实例都有自己的副本。
特性:
- 每个对象实例都有独立的实例变量,这意味着修改一个对象的实例变量不会影响其他对象的实例变量。
- 实例变量的生命周期是与对象实例相同的,即当对象实例被销毁时,实例变量也随之销毁。
示例:
class Example:
def __init__(self):
self.instance_var = 10 # 定义实例变量
# 创建两个对象实例
obj1 = Example()
obj2 = Example()
# 修改 obj1 的实例变量
obj1.instance_var = 20
print(obj1.instance_var) # 输出 20
print(obj2.instance_var) # 输出 10,未受 obj1 修改的影响
在上述示例中,obj1
和 obj2
各自有独立的 instance_var
,它们的值可以不同。
2. 类变量(没有 self.
的变量)
定义与作用:
- 类变量是在类体中定义的,但不属于
__init__
方法,因此没有self.
前缀。 - 类变量在类中所有实例之间共享,一个实例对类变量的修改会影响其他实例,除非在某个实例中重写了该变量。
特性:
- 适合存储类级别的数据,如计数器、共享配置等。
- 可以通过类名或者实例访问,但实例访问时如果重写,会创建一个新的实例变量,而不影响原始类变量。
示例:
class Example:
class_var = 5 # 定义类变量
# 创建两个对象实例
obj1 = Example()
obj2 = Example()
# 修改 obj1 的类变量
obj1.class_var = 10 # obj1 现在有了自己的实例变量 `class_var`
print(obj1.class_var) # 输出 10,obj1 重写了 `class_var`
print(obj2.class_var) # 输出 5,未受 obj1 修改的影响
print(Example.class_var) # 输出 5,类本身的变量未改变
在这里,obj1
修改 class_var
后,实际上创建了一个新的实例变量 class_var
,而 obj2
和 Example
类仍然使用的是原来的类变量。
3. 修改行为和作用域
实例变量:
- 修改实例变量只会影响当前对象,不会影响其他实例或类定义本身。
- 可以通过
self.instance_var
直接在实例方法中访问和修改。
类变量:
- 类变量可以被所有实例共享,任何实例对类变量的直接修改都会影响到其他实例和类本身(除非创建了实例变量)。
- 可以通过
ClassName.class_var
访问和修改,也可以通过实例来访问,但修改时需要小心区分是否在创建实例变量。
深入理解重写行为:
class Example:
class_var = 5
obj = Example()
print(obj.class_var) # 输出 5
# 修改类变量
Example.class_var = 20
print(obj.class_var) # 输出 20,类变量已被类修改
# 创建一个实例变量 `class_var`
obj.class_var = 10
print(obj.class_var) # 输出 10,`obj` 上创建了实例变量
# 类变量不受实例修改的影响
print(Example.class_var) # 输出 20
4. 使用场景
- 实例变量:适用于每个对象需要单独的属性,如用户的个人数据、对象的状态等。
- 类变量:适用于所有对象实例共享的数据,如类级别的统计信息、共享配置、常量等。
注意:滥用类变量可能导致意外的共享数据问题,尤其在多线程或复杂对象交互时要小心使用。
5. 可视化对比
实例变量:
- 定义:
self.attribute
- 访问:
self.attribute
(方法内部),instance.attribute
- 修改:只影响当前实例
类变量:
- 定义:
attribute
(类体中) - 访问:
ClassName.attribute
,instance.attribute
(如果实例没有同名实例变量) - 修改:
ClassName.attribute = value
(全局修改),instance.attribute = value
(创建实例变量)
理解这两者的区别对于编写健壮、清晰的面向对象代码非常重要。