当前位置: 首页 > news >正文

Python 实例属性和类属性

Python 的类和对象是面向对象编程的核心,而属性(attributes)是类和对象中存储数据的地方。Python 的属性分为实例属性类属性,这俩虽然听起来差不多,但用法和行为有挺大的区别。

参考文章:Python 实例属性和类属性 | 简单一点学习 easyeasy.me

1. 什么是实例属性和类属性?

1.1 实例属性

实例属性是属于某个具体对象(实例)的属性。每个对象都有自己的实例属性,互不干扰。就像你和你的朋友每人有自己的手机,手机里的照片、设置啥的都是独一无二的。

  • 特点
    • 通常在 __init__ 方法中通过 self 定义。
    • 每个实例的属性值可以不同。
    • 只能通过实例访问(obj.attribute)。

1.2 类属性

类属性是属于整个类的属性,所有实例共享同一份数据。就像一个班级的班规,所有学生都得遵守同一套规则。

  • 特点
    • 定义在类内部,但不在任何方法内(通常在类开头定义)。
    • 通过类名或实例都可以访问(ClassName.attributeobj.attribute)。
    • 修改类属性会影响所有实例(除非实例覆盖了它)。

2. 怎么定义和使用这两种属性?

2.1 定义实例属性

实例属性一般在 __init__ 方法里用 self 来定义,每次创建对象时都会初始化。

class Dog:def __init__(self, name, age):self.name = name  # 实例属性self.age = age    # 实例属性# 创建两个 Dog 实例
dog1 = Dog("旺财", 3)
dog2 = Dog("小黑", 5)print(dog1.name)  # 输出: 旺财
print(dog2.name)  # 输出: 小黑

上面代码里,nameage 是实例属性,dog1dog2 各有一份,互不影响。

2.2 定义类属性

类属性直接在类里定义,不需要 self,通常放在 __init__ 方法外面。

class Dog:species = "Canis familiaris"  # 类属性def __init__(self, name, age):self.name = nameself.age = agedog1 = Dog("旺财", 3)
dog2 = Dog("小黑", 5)print(dog1.species)  # 输出: Canis familiaris
print(dog2.species)  # 输出: Canis familiaris
print(Dog.species)   # 输出: Canis familiaris

species 是类属性,dog1dog2Dog 类都能访问它,因为它是所有实例共享的。

3. 访问和修改属性的区别

3.1 访问属性

  • 实例属性:只能通过实例访问,比如 dog1.name
  • 类属性:可以通过类名(Dog.species)或实例(dog1.species)访问。
class Dog:species = "Canis familiaris"def __init__(self, name):self.name = namedog = Dog("旺财")
print(dog.name)      # 实例属性,输出: 旺财
print(dog.species)   # 类属性,输出: Canis familiaris
print(Dog.species)   # 类属性,输出: Canis familiaris

3.2 修改属性

  • 实例属性:修改只影响当前实例。
  • 类属性:通过类名修改会影响所有实例;通过实例修改会“遮盖”类属性(实际上是为实例创建了一个同名的实例属性)。
class Dog:species = "Canis familiaris"def __init__(self, name):self.name = namedog1 = Dog("旺财")
dog2 = Dog("小黑")# 修改类属性
Dog.species = "Canis lupus"
print(dog1.species)  # 输出: Canis lupus
print(dog2.species)  # 输出: Canis lupus# 通过实例“修改”类属性(实际上创建了实例属性)
dog1.species = "Doggo"
print(dog1.species)  # 输出: Doggo(实例属性)
print(dog2.species)  # 输出: Canis lupus(类属性)
print(Dog.species)   # 输出: Canis lupus(类属性)

注意:dog1.species = "Doggo" 并不是修改了类属性,而是给 dog1 创建了一个新的实例属性 species,遮盖了类属性。

4. 实际场景中的用法

4.1 实例属性的典型场景

实例属性适合存储每个对象独有的数据,比如名字、年龄、ID 等等。就像下面这个例子:

class Student:def __init__(self, name, student_id):self.name = nameself.student_id = student_idself.grades = []def add_grade(self, grade):self.grades.append(grade)student1 = Student("小明", "001")
student2 = Student("小红", "002")student1.add_grade(90)
student2.add_grade(85)print(student1.grades)  # 输出: [90]
print(student2.grades)  # 输出: [85]

每个学生有自己的成绩单,互不干扰,这就是实例属性的典型用法。

4.2 类属性的典型场景

类属性适合存储所有实例共享的数据,比如计数器、默认配置等。比如下面这个例子,用类属性来统计创建了多少个对象:

class Dog:count = 0  # 类属性,用来计数def __init__(self, name):self.name = nameDog.count += 1  # 每次创建实例,计数加 1dog1 = Dog("旺财")
dog2 = Dog("小黑")
dog3 = Dog("大黄")print(Dog.count)  # 输出: 3

count 是类属性,记录了总共创建了多少只狗,所有的狗共享这个计数器。

5. 注意事项和常见坑

5.1 实例属性和类属性的命名冲突

如果实例属性和类属性同名,实例属性会“遮盖”类属性。前面已经看到过例子了,这种情况要小心,别搞混了。

5.2 可变类属性的陷阱

如果类属性是可变对象(比如列表或字典),所有实例共享同一份数据,修改会影响所有实例。

class Dog:tricks = []  # 类属性,是一个列表def __init__(self, name):self.name = namedef add_trick(self, trick):self.tricks.append(trick)dog1 = Dog("旺财")
dog2 = Dog("小黑")dog1.add_trick("坐下")
dog2.add_trick("握手")print(dog1.tricks)  # 输出: ['坐下', '握手']
print(dog2.tricks)  # 输出: ['坐下', '握手']

这可能不是你想要的!因为 tricks 是类属性,所有狗共享同一个列表。如果你想要每只狗有自己的技能列表,应该用实例属性:

class Dog:def __init__(self, name):self.name = nameself.tricks = []  # 实例属性def add_trick(self, trick):self.tricks.append(trick)dog1 = Dog("旺财")
dog2 = Dog("小黑")dog1.add_trick("坐下")
dog2.add_trick("握手")print(dog1.tricks)  # 输出: ['坐下']
print(dog2.tricks)  # 输出: ['握手']

5.3 动态添加实例属性

Python 允许动态给实例添加属性,但要小心,这可能会让代码不好维护。

class Dog:def __init__(self, name):self.name = namedog = Dog("旺财")
dog.age = 3  # 动态添加实例属性
print(dog.age)  # 输出: 3

虽然很灵活,但建议尽量在 __init__ 里定义所有属性,保持代码清晰。

6. 总结

  • 实例属性:每个对象独有,定义在 __init__ 里,用 self 访问,适合存储对象特有的数据。
  • 类属性:所有实例共享,定义在类里,用类名或实例访问,适合存储共享数据。
  • 注意事项:小心命名冲突和可变类属性的陷阱,尽量在 __init__ 里定义实例属性。
http://www.lryc.cn/news/616052.html

相关文章:

  • 安卓录音方法
  • Java 后端性能优化实战:从 SQL 到 JVM 调优
  • 深入解析React Diff 算法
  • Word XML 批注范围克隆处理器
  • React:useEffect 与副作用
  • MyBatis的xml中字符串类型判空与非字符串类型判空处理方式
  • 秋招春招实习百度笔试百度管培生笔试题库百度非技术岗笔试|笔试解析和攻略|题库分享
  • wordpress语言包制作工具
  • python正则表达式里面有特殊符号如何处理
  • 亚麻云之静态资源管家——S3存储服务实战
  • Day41--动态规划--121. 买卖股票的最佳时机,122. 买卖股票的最佳时机 II,123. 买卖股票的最佳时机 III
  • LeetCode 组合总数
  • AI质检数据准备利器:基于Qt/QML 5.14的图像批量裁剪工具开发实战
  • Python 2025:最新技术趋势与展望
  • Text2SQL 自助式数据报表开发(Chat BI)
  • 解决 .NET Core 6.0 + PostgreSQL 网站首次连接缓慢问题
  • 嵌入式软件分层架构的设计原理与实践验证(有限状态机理解及结构体封装理解)
  • spring-ai整合PGVector实现RAG
  • WinForm之TreeView控件
  • Baumer高防护相机如何通过YoloV8深度学习模型实现道路坑洼的检测识别(C#代码UI界面版)
  • [激光原理与应用-223]:机械 - 机加厂加工机械需要2D还是3D图?
  • jvm有哪些垃圾回收器,实际中如何选择?
  • 本地WSL部署接入 whisper + ollama qwen3:14b 总结字幕校对增强版
  • Code Exercising Day 10 of “Code Ideas Record“:StackQueue part02
  • 低版本 IntelliJ IDEA 使用高版本 JDK 语言特性的问题
  • IDEA 如何导入系统设置
  • 基于ECharts的智慧社区数据可视化
  • IDEA 快捷编辑指南
  • IntelliJ IDEA 2025.2 重磅发布
  • OneCode 3.0 可视化功能全面分析:从开发者到用户的全场景解析