摘要: 本文是笔者作为计算机专业学生在深入学习Python面向对象编程时的详细笔记。文章首先剖析了面向对象与面向过程的思想差异,随后系统梳理了类与对象的定义、self的深层含义、构造与析构方法的应用,以及对象属性与类属性的区别。最后通过三个经典实战案例,展示了如何利用OOP思想解决实际问题。旨在通过理论与实践的结合,打通Python进阶的核心脉络。


上节课回顾:Python进阶核心特性

在正式进入面向对象编程之前,我们先快速复盘一下Python进阶路上的三个关键知识点,它们是写出高效、优雅Python代码的基础:

1. 列表推导式 (List Comprehension)
列表推导式提供了一种创建列表的简洁方式,它能让代码从多行循环变为一行表达式。

  • 核心语法: [表达式 for 变量 in 可迭代对象 if 条件]
  • 优势: 代码更加Pythonic,执行效率通常高于传统的for循环。

2. 生成器 (Generator)
生成器是一种特殊的迭代器,它不将所有值存储在内存中,而是按需生成数据。

  • 创建方式: 将列表推导式的 [] 改为 (),或者在函数中使用 yield 关键字。
  • 核心价值: 内存管理。非常适合处理大数据流或无限序列,实现了“按需计算”,极大地节省了内存资源。

3. 模块与包 (Modules and Packages)
随着项目规模变大,代码组织变得至关重要。

  • 模块 (Module): 一个 .py 文件就是一个模块,用于组织函数和类。
  • 包 (Package): 包含 __init__.py 文件的文件夹,用于管理多个相关的模块。
  • 管理工具: 使用 pip 进行第三方包的安装与管理(如 pip install),利用虚拟环境和 requirements.txt 可以锁定项目依赖。
一、 理解面向对象思想:从“怎么做”到“谁来做”

在学习语法之前,我们首先要转变思维模式。

  • 面向过程 (Procedural): 侧重于解决问题的步骤。例如“小猫吃食物”,面向过程关注的是“先闻一闻 -> 再舔一舔 -> 最后咬一咬”。代码是按顺序执行的指令集。
  • 面向对象 (OOP): 侧重于解决问题中涉及的对象。同样“小猫吃食物”,面向对象关注的是“小猫”这个对象,它具备“闻、舔、咬”的能力。我们不需要关心具体过程,只需要指挥“小猫”去吃。

核心概念:

  • 类 (Class): 是对一类事物的抽象描述(如“人类”、“狗”),不占用内存。
  • 对象 (Object): 是类的具体实例(如“王五”、“旺财”),由类创建,占用内存空间。

二、 核心语法详解:类与对象的构建

1. 类的定义与使用
在Python中,使用 class 关键字定义类。类名通常采用大驼峰命名法(如 MyClass)。
类体中包含两部分内容:

  • 属性 (Attribute): 描述事物的静态特征(如人的姓名、年龄)。
  • 方法 (Method): 描述事物的行为(如人可以吃饭、玩游戏)。

2. self 关键字详解
这是初学者最容易困惑的点。

  • 本质: self 不是关键字,只是一个习惯性的形参名(代表当前对象的引用)。
  • 含义: 哪个对象调用方法,self 就指向哪个对象。
  • 作用: 让方法内部可以访问该对象的属性或其他方法。调用时无需手动传值,由解释器自动传入。

3. 构造方法 __init__ 与 析构方法 __del__

  • 构造方法 (__init__): 在创建对象时自动调用,用于给对象的属性赋初始值。如果类中没有定义,Python会提供一个默认的无参构造函数。
  • 析构方法 (__del__): 在对象销毁(被垃圾回收)时自动调用,通常用于资源释放(如关闭文件、数据库连接)。

代码演示:

class Person:
    # 构造方法:初始化对象属性
    def __init__(self, name, age):
        self.name = name  # 对象属性
        self.age = age
        print("对象被创建了!")
    
    # 普通方法
    def introduce(self):
        print(f"我是{self.name}, 今年{self.age}岁")

    # 析构方法:清理资源
    def __del__(self):
        print("对象被销毁了!")

# 创建对象(此时自动调用 __init__)
p = Person("小明", 20)
p.introduce()
# 程序结束时自动调用 __del__

三、 属性进阶:类属性与对象属性

在Python类中,属性分为两种,它们的查找机制和作用域不同:

  1. 类属性 (Class Attribute): 定义在类内部、方法外部。它被该类的所有实例共享
  2. 对象属性 (Instance Attribute): 定义在 __init__ 或其他方法中,通过 self.属性名 定义。它属于特定的实例

访问优先级:
当通过对象访问属性时,Python会先查找对象属性,如果没有,再去查找类属性。如果对象属性与类属性同名,对象属性会“屏蔽”类属性。

代码演示:

我们首先创建一个简单的类,代码如下:

class Person:
    # 类属性
    sex = "男"
    def __init__(self, name):
        # 对象属性
        self.name = name
p = Person('小明')

首先我们使用对象属性来调用对象属性

print(p.name)

打印结果如图:

接下来我们用类属性来调用对象属性

print(Person.name)

打印结果如图:

打印结果我们的代码会报错,在Person类中无法找到name这个属性。综上所述,对象属性的调用只能用对象属性,而不能用类属性。

基于这个类我们继续看类属性的调用

首先我们用类属性调用:

print(Person.sex)

打印结果如图:

接下来我们使用对象属性来调用:

print(p.sex)

打印结果如图:

综上所述,调用类属性可以用类属性,也可以用对象属性。推荐使用类属性。

我们在上述的类中加入age属性。

class Person:
    # 类属性
    sex = "男"
    age = 18
    def __init__(self, name, age):
        # 对象属性
        self.name = name
        self.age = age

p = Person('小明', '22')

我们先使用类属性来调用类属性:

print(Person.age) 

打印结果如图:

接下来用对象属性来调用:

print(p.age) 

打印结果如图:

我们会发现,用对象属性调用类属性打印的是对象属性的值。所以,对象属性优先获取的是对象属性。

💡 建议:操作对象属性时尽量用对象,操作类属性时尽量用类名,这样不易报错和混肴。

四、 实战演练:OOP思想解决实际问题

结合我做的课后作业,以下是几个典型的OOP应用场景代码:

1. 人物行为模拟

class Person:
    def __init__(self, name):
        self.name = name
    
    def run(self, place, shoes):
        print(f"{self.name}穿着{shoes}在{place}跑步")

# 实例化对象
xiaoming = Person("小明")
xiaoming.run("城墙", "白色运动鞋")

代码运行结果如图:

2. 银行账户管理

class Account:
    def __init__(self, name, balance):
        self.name = name
        self.balance = balance
    
    def save_money(self, money):
        self.balance += money
        print(f"存款成功,余额为{self.balance}")
    
    def get_money(self, money):
        if self.balance >= money:
            self.balance -= money
            print(f"取款成功,余额为{self.balance}")
        else:
            print("余额不足!")

# 创建账户
my_account = Account("小王", 100)
my_account.save_money(200)  # 存款
my_account.get_money(50)    # 取款

代码运行结果如图:

3. 几何图形计算(组合关系)
涉及两个类:圆 (Circle) 和 点 (Point)

class Circle:
    def __init__(self, r, center_point):
        self.r = r
        self.center = center_point  # 对象作为另一个对象的属性(组合)
    
    def area(self):
        return 3.14 * self.r ** 2

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

# 创建点对象
center = Point(0, 0)
# 创建圆对象,传入点对象
c = Circle(5, center)
print("圆的面积:", c.area())

代码运行结果如图:


五、 总结与反思

通过这次系统的学习,我对Python面向对象编程有了更深刻的认识:

  1. 思想转变: 面向对象的核心不是“如何一步步做”,而是“找到谁来做”。这将复杂的问题简单化,让我们从执行者变成了指挥者。
  2. self 的理解: 它是连接对象和方法的桥梁,理解了“谁调用,self 就是谁”,就理解了实例方法的本质。
  3. 内存管理: 类不占内存,对象才占内存。构造方法和析构方法让我们能更好地控制资源的初始化和释放。
  4. 属性区分: 类属性用于共享数据,对象属性用于描述个体差异。

未来的计划: 接下来我将深入学习面向对象的三大特征(封装、继承、多态),并尝试用OOP思想去重构之前的代码项目。


Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐