09. Python面向对象编程(OOP入门全解析:从思想到实战的深度总结)
摘要: 本文是笔者作为计算机专业学生在深入学习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类中,属性分为两种,它们的查找机制和作用域不同:
- 类属性 (Class Attribute): 定义在类内部、方法外部。它被该类的所有实例共享。
- 对象属性 (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面向对象编程有了更深刻的认识:
- 思想转变: 面向对象的核心不是“如何一步步做”,而是“找到谁来做”。这将复杂的问题简单化,让我们从执行者变成了指挥者。
self的理解: 它是连接对象和方法的桥梁,理解了“谁调用,self就是谁”,就理解了实例方法的本质。- 内存管理: 类不占内存,对象才占内存。构造方法和析构方法让我们能更好地控制资源的初始化和释放。
- 属性区分: 类属性用于共享数据,对象属性用于描述个体差异。
未来的计划: 接下来我将深入学习面向对象的三大特征(封装、继承、多态),并尝试用OOP思想去重构之前的代码项目。
更多推荐



所有评论(0)