Python类属性和实例属性的解析

一、类属性(Class Attribute)

1. 定义:

  • 属于类本身的属性,所有实例共享。
  • 直接在类内部声明(不在 init 中)。

2. 访问:

通过类名或实例均可访问(但修改时需谨慎)。

class Car:
    wheels = 4  # 类属性:所有汽车有4个轮子

    def __init__(self, brand):
        self.brand = brand  # 实例属性

# 访问类属性
print(Car.wheels)  # 输出: 4
car = Car("Tesla")
print(car.wheels)  # 输出: 4(通过实例访问)

3. 修改类属性

  • 正确方式:通过类名修改,所有实例会继承新值。
  • 错误方式:通过实例修改会创建同名实例属性,覆盖类属性。
# 正确修改类属性
Car.wheels = 6
print(Car.wheels)  # 输出: 6
print(car.wheels)  # 输出: 6(所有实例同步更新)

# 错误修改(实际创建实例属性)
car.wheels = 8
print(car.wheels)   # 输出: 8(实例属性)
print(Car.wheels)   # 输出: 6(类属性未变)

4. 作用:

  • 共享数据:所有实例共用同一份数据,适合存储与类相关的全局信息。
class Dog:
    species = "Canis familiaris"  # 类属性:所有狗的物种相同
    
    def __init__(self, name):
        self.name = name  # 实例属性:每只狗的名字不同
  • 节省内存:类属性只存储一次,避免每个实例重复存储相同数据。
  • 配置默认值:为实例提供默认值,实例可以覆盖这些值。
class User:
    default_role = "guest"  # 默认角色
    
    def __init__(self, role=None):
        self.role = role or User.default_role  # 实例可覆盖默认值
  • 统计类级信息:例如统计实例数量。
class Player:
    count = 0  # 类属性统计实例数
    
    def __init__(self):
        Player.count += 1

二、实例属性(Instance Attribute)

1. 定义:

  • 属于某个具体实例的属性,每个实例独立。
  • init 方法中通过 self.xxx 初始化。

2. 访问:

只能通过实例访问,每个实例独立。

class User:
    def __init__(self, name, age):
        self.name = name  # 实例属性
        self.age = age    # 实例属性

user1 = User("Alice", 30)
user2 = User("Bob", 25)
print(user1.name)  # 输出: Alice
print(user2.name)  # 输出: Bob

3. 作用:

  • 存储对象状态:保存对象的独特数据。
class Car:
    def __init__(self, color, speed):
        self.color = color  # 实例属性:每辆车的颜色不同
        self.speed = speed  # 实例属性:每辆车的速度不同
  • 动态属性管理:允许在运行时动态添加或修改属性。
car = Car("red", 100)
car.year = 2023  # 动态添加实例属性
  • 隔离数据:不同实例的属性互不影响。
a = Car("red", 100)
b = Car("blue", 80)
a.speed = 120  # 仅修改 a 的 speed,不影响 b

三、类属性与实例属性的混合使用

1. 用类属性为实例提供默认值

class Settings:
    theme = "light"  # 类属性作为默认主题

    def __init__(self):
        self.theme = Settings.theme  # 实例属性初始化为类属性值

settings = Settings()
settings.theme = "dark"  # 修改实例属性,不影响类属性
print(settings.theme)    # 输出: dark
print(Settings.theme)    # 输出: light

2. 类属性与实例属性同名时的优先级

class MyClass:
    attr = "类属性"  # 类属性

    def __init__(self):
        self.attr = "实例属性"  # 同名实例属性

obj = MyClass()
print(obj.attr)      # 输出: 实例属性(实例属性优先级更高)
print(MyClass.attr)  # 输出: 类属性

四、注意事项与常见错误

1. 避免通过实例修改类属性

class Animal:
    category = "哺乳动物"

dog = Animal()
dog.category = "爬行动物"  # 错误!实际创建了实例属性
print(dog.category)        # 输出: 爬行动物
print(Animal.category)     # 输出: 哺乳动物(类属性未变)

2. 可变类属性的副作用

若类属性是可变对象(如列表、字典),所有实例共享同一份数据:

class Student:
    grades = []  # 类属性是列表

    def add_grade(self, grade):
        self.grades.append(grade)

s1 = Student()
s2 = Student()
s1.add_grade(90)
s2.add_grade(80)
print(s1.grades)  # 输出: [90, 80](所有实例共享)

解决方案:init 中初始化可变对象:

class Student:
    def __init__(self):
        self.grades = []  # 实例属性,每个实例独立

    def add_grade(self, grade):
        self.grades.append(grade)

s1 = Student()
s2 = Student()
s1.add_grade(90)
s2.add_grade(80)
print(s1.grades)  # 输出: [90]
print(s2.grades)  # 输出: [80]

五、最佳实践

  1. 类属性用于:
    • 全局配置、共享数据、统计信息。
    • 避免存储可变状态(除非明确需要共享)。
  2. 实例属性用于:
    • 对象特有的状态、动态数据。
    • 优先在 __init__ 中初始化。
  3. 命名规范:
    • 类属性用全大写表示常量(如 MAX_SPEED = 200)。
    • 实例属性用蛇形命名法(如 user_name)。

总结

场景 类属性 实例属性
归属 属于类 属于实例
定义位置 类内部直接声明 __init__ 中通过 self.xxx 初始化
数据共享性 所有实例共享 实例独立
修改影响范围 修改后所有实例可见 仅影响当前实例
修改方式 通过类名修改(ClassName.attr) 通过实例修改(self.attr)
典型用途 全局配置、统计计数、默认值 对象状态、临时数据
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容