Python面向对象编程详解:从零开始掌握类的声明与使用

🙋‍♀️ 个人主页颜颜yan_

本期精彩 :Python面向对象编程详解:从零开始掌握类的声明与使用

🏆 热门专栏零基础玩转Python爬虫:手把手教你成为数据猎人

🚀 专栏亮点 :零基础友好 | 实战案例丰富 | 循序渐进教学 | 代码详细注释

💡 学习收获:掌握爬虫核心技术,成为数据采集高手,开启你的数据科学之旅!

🔥 如果觉得文章有帮助,别忘了点赞👍 收藏⭐ 关注🚀,你的支持是我创作的最大动力!


文章目录


前言

面向对象是Python中非常重要的一种编程方式,它允许我们将数据和功能组织成可重用的"类"。理解Python类的声明和使用是从初级程序员迈向中级程序员的关键一步。


类的成员

在深入学习Python类的声明之前,我们需要了解一个类主要包含哪些成员。下图展示了Python类的基本结构:

一个完整的Python类包含以下几个部分:

  1. 类名称:定义类的名称,通常使用大驼峰命名法(即每个单词的首字母大写)
  2. 类变量:由所有类的实例共享的变量
  3. 构造方法:用于创建类的实例并初始化实例变量
  4. 实例变量:每个实例独有的变量
  5. 实例方法:操作实例数据的函数
  6. 类方法 :使用@classmethod装饰器定义,操作类变量的函数
  7. 静态方法 :使用@staticmethod装饰器定义,不访问实例或类变量的功能函数

下面是一个简单的类声明示例:

python 复制代码
class Student:
    # 类变量 - 所有实例共享
    school_name = "Python"
    student_count = 0
    # 构造方法
    def __init__(self, name, age):
        # 实例变量 - 每个实例独立
        self.name = name
        self.age = age
        Student.student_count += 1
    
    # 实例方法
    def introduce(self):
        return f"你好,我是{self.name},今年{self.age}岁,就读于{Student.school_name}"
    
    # 类方法
    @classmethod
    def get_student_count(cls):
        return f"当前学生总数:{cls.student_count}人"
    
    # 静态方法
    @staticmethod
    def school_motto():
        return "学习编程,改变未来!"

接下来,我们将详细讲解每种类成员的特点和用法。

实例变量与构造方法

什么是实例变量?

实例变量是属于类的某个特定实例(对象)的变量。每个实例都有自己的一份实例变量副本,修改一个实例的变量不会影响其他实例的变量。实例变量通常在类的构造方法__init__中定义,并使用self关键字引用。

构造方法(init

构造方法是类中的一个特殊方法,名称固定为__init__。当我们创建一个类的新实例时,构造方法会被自动调用。其主要作用有:

  1. 初始化实例的属性(实例变量)
  2. 执行对象创建时需要的操作
  3. 接收用户提供的参数并将其保存到实例变量中

构造方法的第一个参数总是self,它指向被创建的实例本身。

python 复制代码
class Student:
    # 构造方法
    def __init__(self, name, age):
        # 实例变量
        self.name = name  # 学生姓名
        self.age = age    # 学生年龄
        self.grades = []  # 存储学生成绩的列表
        
    # 一个添加成绩的方法
    def add_grade(self, subject, score):
        self.grades.append({"subject": subject, "score": score})

让我们看看实例变量在实际使用中的特点:

python 复制代码
# 创建两个学生实例
student1 = Student("小明", 18)
student2 = Student("小红", 17)

# 修改student1的name
student1.name = "小明明"

# 查看两个实例的name
print(f"student1.name: {student1.name}")  # 输出: student1.name: 小明明
print(f"student2.name: {student2.name}")  # 输出: student2.name: 小红

从上面的输出可以看到,修改student1name不会影响到student2name,这证明实例变量确实是各个实例独立拥有的。

实例变量的动态添加

Python的动态特性允许我们在对象创建后动态添加新的实例变量:

python 复制代码
# 在对象创建后添加新的实例变量
student1.email = "xiaoming@example.com"

# 访问新添加的实例变量
print(student1.email)  # 输出: xiaoming@example.com

# student2没有email属性,访问会引发错误
# print(student2.email)  # AttributeError: 'Student' object has no attribute 'email'

这种动态特性虽然灵活,但在大型程序中可能导致代码难以维护,因此建议在构造方法中预先定义所有实例变量。

实例方法

实例方法是定义在类中,用于操作实例数据的函数。它们是类对象具有的行为和功能。

实例方法的特点

  1. 第一个参数始终是self,表示调用该方法的实例本身
  2. 可以访问和修改实例变量
  3. 可以访问类变量
  4. 必须通过类的实例来调用

下面是一个实例方法的示例:

python 复制代码
class Calculator:
    def __init__(self, name):
        self.name = name
        self.result = 0
    
    def add(self, a, b=None):
        """
        加法计算方法
        如果只提供一个参数,则将结果加上这个值
        如果提供两个参数,则计算两数之和
        """
        if b is None:
            self.result += a
            return self.result
        else:
            return a + b
    
    def subtract(self, a, b=None):
        """减法计算方法"""
        if b is None:
            self.result -= a
            return self.result
        else:
            return a - b
    
    def reset(self):
        """重置结果为0"""
        self.result = 0
        return self.result
    
    def __str__(self):
        """字符串表示方法"""
        return f"{self.name}计算器 (当前结果: {self.result})"

使用实例方法的示例:

python 复制代码
# 创建计算器实例
calc = Calculator("科学")
print(calc)  # 输出: 科学计算器 (当前结果: 0)

# 使用实例方法进行独立计算
print(f"5 + 3 = {calc.add(5, 3)}")    # 输出: 5 + 3 = 8
print(f"10 - 4 = {calc.subtract(10, 4)}")  # 输出: 10 - 4 = 6

# 使用实例方法进行累加计算
print(f"当前结果: {calc.result}")      # 输出: 当前结果: 0
print(f"加5后结果: {calc.add(5)}")     # 输出: 加5后结果: 5
print(f"再加10后结果: {calc.add(10)}") # 输出: 再加10后结果: 15
print(f"减3后结果: {calc.subtract(3)}") # 输出: 减3后结果: 12
print(f"重置后结果: {calc.reset()}")   # 输出: 重置后结果: 0

特殊实例方法

Python中有一些特殊的实例方法,它们的名称以双下划线开头和结尾(也称为"魔术方法"或"双下方法")。这些方法可以让我们自定义类的行为:

  • __init__: 构造方法,创建实例时调用
  • __str__: 将对象转换为字符串表示,在print()函数中调用
  • __repr__: 返回对象的"官方"字符串表示,在交互式环境中显示
  • __len__: 定义当len()函数应用于对象时的行为
  • __add__, __sub__等: 定义对象的算术运算行为

类变量

类变量是在类定义中、方法之外声明的变量。它们属于类本身而不是某个特定的实例,因此被类的所有实例共享。

类变量的特点

  1. 在类内部定义,但在任何方法之外
  2. 所有实例共享同一个变量值
  3. 可以通过类名或实例访问
  4. 修改类变量会影响所有实例

代码示例

python 复制代码
class Student:
    # 类变量
    school_name = "Python"
    student_count = 0
    
    def __init__(self, name, age):
        self.name = name
        self.age = age
        # 使用类变量记录学生人数
        Student.student_count += 1

使用类变量:

python 复制代码
# 创建两个学生实例
student1 = Student("小明", 18)
student2 = Student("小红", 17)

# 访问类变量
print(f"通过类名访问: {Student.school_name}")  # 输出: 通过类名访问: Python编程学院
print(f"通过实例访问: {student1.school_name}")  # 输出: 通过实例访问: Python编程学院

# 修改类变量
Student.school_name = "Python高级编程学院"

# 查看修改后的类变量
print(f"修改后通过类访问: {Student.school_name}")  # 输出: 修改后通过类访问: Python高级编程学院
print(f"修改后通过student1访问: {student1.school_name}")  # 输出: 修改后通过student1访问: Python高级编程学院
print(f"修改后通过student2访问: {student2.school_name}")  # 输出: 修改后通过student2访问: Python高级编程学院

注意事项:类变量的陷阱

当通过实例修改类变量时要格外小心,因为这可能会在实例中创建一个同名的实例变量,而不是修改类变量:

python 复制代码
# 通过实例修改类变量
student1.school_name = "AI学院"  # 这实际上创建了一个名为school_name的实例变量

# 查看结果
print(f"Student.school_name: {Student.school_name}")  # 输出: Student.school_name: Python高级编程学院
print(f"student1.school_name: {student1.school_name}")  # 输出: student1.school_name: AI学院
print(f"student2.school_name: {student2.school_name}")  # 输出: student2.school_name: Python高级编程学院

要正确修改类变量,应该通过类名来操作:Student.school_name = "新值"

类方法

类方法是使用@classmethod装饰器声明的方法,它们主要操作类变量而不是实例变量。

类方法的特点

  1. 使用@classmethod装饰器声明
  2. 第一个参数通常命名为cls,代表类本身(而不是实例)
  3. 可以访问和修改类变量
  4. 可以通过类名或实例调用
  5. 不能直接访问实例变量(因为没有self参数)

类方法的应用场景

  1. 修改或访问类变量
  2. 创建工厂方法(替代构造方法创建实例的方法)
  3. 实现与类相关但不需要实例的功能

代码示例

python 复制代码
class DateUtil:
    # 类变量
    date_format = "%Y-%m-%d"
    
    def __init__(self, date_string):
        self.date_string = date_string
    
    # 类方法 - 修改类变量
    @classmethod
    def set_date_format(cls, new_format):
        old_format = cls.date_format
        cls.date_format = new_format
        return f"日期格式已从 {old_format} 更改为 {new_format}"
    
    # 类方法 - 工厂方法创建实例
    @classmethod
    def create_today(cls):
        import datetime
        today = datetime.datetime.now().strftime(cls.date_format)
        return cls(today)  # 返回类的新实例

使用类方法:

python 复制代码
# 使用类方法修改类变量
print(DateUtil.set_date_format("%Y/%m/%d"))  # 输出: 日期格式已从 %Y-%m-%d 更改为 %Y/%m/%d

# 使用工厂方法创建实例
today_util = DateUtil.create_today()
print(f"今天的日期字符串: {today_util.date_string}")  # 输出类似: 今天的日期字符串: 2025/07/27

静态方法

静态方法是使用@staticmethod装饰器声明的方法,它们与类相关但不需要访问类变量或实例变量。

静态方法的特点

  1. 使用@staticmethod装饰器声明
  2. 不自动接收特殊的第一个参数(没有selfcls
  3. 不能直接访问类变量或实例变量
  4. 可以通过类名或实例调用
  5. 本质上就是放在类命名空间中的普通函数

静态方法的应用场景

  1. 实现与类相关但不需要访问类状态的辅助功能
  2. 组织代码结构,将相关功能放在一起
  3. 创建不依赖于类状态的实用工具方法

代码示例

python 复制代码
class DateUtil:
    # 类变量
    date_format = "%Y-%m-%d"
    
    # 静态方法 - 验证日期格式
    @staticmethod
    def is_valid_date(date_string, date_format=None):
        import datetime
        if date_format is None:
            date_format = DateUtil.date_format
            
        try:
            datetime.datetime.strptime(date_string, date_format)
            return True
        except ValueError:
            return False
    
    # 静态方法 - 计算两个日期之间的天数
    @staticmethod
    def days_between(date1, date2, date_format=None):
        import datetime
        if date_format is None:
            date_format = DateUtil.date_format
            
        try:
            d1 = datetime.datetime.strptime(date1, date_format)
            d2 = datetime.datetime.strptime(date2, date_format)
            return abs((d2 - d1).days)
        except ValueError:
            return "日期格式无效"

使用静态方法的示例:

python 复制代码
# 使用静态方法验证日期格式
print(f"'2023-07-15'是有效日期吗? {DateUtil.is_valid_date('2023-07-15')}")  # 输出: '2023-07-15'是有效日期吗? True
print(f"'2023/07/15'是有效日期吗? {DateUtil.is_valid_date('2023/07/15')}")  # 输出: '2023/07/15'是有效日期吗? False
print(f"'2023/07/15'是有效日期吗(使用自定义格式)? {DateUtil.is_valid_date('2023/07/15', '%Y/%m/%d')}")  # 输出: '2023/07/15'是有效日期吗(使用自定义格式)? True

# 计算两个日期之间的天数
print(f"'2023-01-01'和'2023-12-31'之间的天数: {DateUtil.days_between('2023-01-01', '2023-12-31')}")  # 输出: '2023-01-01'和'2023-12-31'之间的天数: 364

注意静态方法不能直接访问类变量,如果需要访问类变量,它通常会通过类名来引用(如示例中的DateUtil.date_format)。


🎯 与我一起学习成长

理解这些概念对于编写高质量的面向对象Python代码至关重要。面向对象编程的核心理念是将数据(变量)和行为(方法)组合在一起,形成有意义的实体(类)。通过合理使用不同类型的变量和方法,我们可以创建出结构清晰、易于维护的代码。🐍✨

我是颜颜yan_,一名专注于技术分享的博主。如果这篇文章对你有帮助,欢迎关注我的更多精彩内容!

📚 专栏推荐

💬 期待与你交流

  • 有疑问?欢迎在评论区留言讨论
  • 想深入学习?关注我获取更多优质教程
  • 觉得有用?别忘了点赞👍 收藏⭐ 关注🚀
相关推荐
Villiam_AY2 小时前
Redis 缓存机制详解:原理、问题与最佳实践
开发语言·redis·后端
UQWRJ3 小时前
菜鸟教程R语言一二章阅读笔记
开发语言·笔记·r语言
岁忧4 小时前
macOS配置 GO语言环境
开发语言·macos·golang
朝朝又沐沐5 小时前
算法竞赛阶段二-数据结构(36)数据结构双向链表模拟实现
开发语言·数据结构·c++·算法·链表
毛飞龙5 小时前
Python类(class)参数self的理解
python··self
魔尔助理顾问5 小时前
系统整理Python的循环语句和常用方法
开发语言·后端·python
Ares-Wang5 小时前
JavaScript》》JS》 Var、Let、Const 大总结
开发语言·前端·javascript
GEM的左耳返6 小时前
Java面试全攻略:Spring生态与微服务架构实战
spring boot·redis·spring cloud·微服务·kafka·java面试
遇见尚硅谷6 小时前
C语言:*p++与p++有何区别
c语言·开发语言·笔记·学习·算法
程序员勋勋16 小时前
Redis的String数据类型底层实现
数据库·redis·缓存