Python: 类与对象
前几课我们用函数组织代码,这是"面向过程"的方式——关注"做什么"。而面向对象编程(OOP)关注的是"谁来做"——把数据和操作数据的方法打包成一个对象。Python 一切皆对象,理解 OOP 是进阶的关键一步。
1. 什么是类和对象
类(class)是模板,对象(object)是根据模板创建的具体实例。
PYTHON
# 定义一个"狗"的类——就是模板
class Dog:
pass
# 根据模板创建具体的"狗"对象
my_dog = Dog()
print(type(my_dog)) # <class '__main__.Dog'>
print(my_dog) # <__main__.Dog object at 0x...>
就像"狗"这个品种是一个概念(类),你家养的那条叫旺财的狗(对象)是具体的实例。一个类可以创建无数个对象。
💡 现实类比: 类是"设计图纸",对象是"按图纸造出来的实物"。一张图纸可以造很多个实物,每个实物有自己的状态(比如不同的狗有不同的名字和年龄)。
2. __init__:构造方法
当创建对象时,__init__ 方法会自动被调用,用来初始化对象的属性:
PYTHON
class Dog:
"""狗类"""
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age
# 创建对象时传入参数
dog1 = Dog("旺财", 3)
dog2 = Dog("小白", 1)
print(dog1.name) # 旺财
print(dog2.name) # 小白
print(dog1.age) # 3
❗注意:
__init__不是构造函数——对象已经创建好了才调用它。真正的构造函数是__new__,但日常几乎不需要动它。__init__的第一个参数永远是self,代表当前对象实例。
▶ 示例:定义学生类(难度⭐)
PYTHON
class Student:
"""学生类"""
def __init__(self, name, student_id, score):
self.name = name
self.student_id = student_id
self.score = score
def introduce(self):
"""自我介绍"""
return f"我叫{self.name},学号{self.student_id},本次考试{self.score}分。"
def is_pass(self):
"""判断是否及格"""
return self.score >= 60
# 创建学生对象
s1 = Student("Alice", "2024001", 85)
s2 = Student("Bob", "2024002", 45)
print(s1.introduce()) # 我叫Alice,学号2024001,本次考试85分。
print(s2.introduce()) # 我叫Bob,学号2024002,本次考试45分。
print(f"Alice及格吗?{s1.is_pass()}") # True
print(f"Bob及格吗?{s2.is_pass()}") # False
输出:
TEXT
📖 仅展示
# 函数定义成功
3. 方法:对象的行为
类中定义的函数叫方法,第一个参数永远是 self——代表调用这个方法的对象本身。
PYTHON
class Calculator:
"""简单计算器"""
def __init__(self):
self.result = 0
def add(self, value):
self.result += value
return self
def subtract(self, value):
self.result -= value
return self
def show(self):
return self.result
calc = Calculator()
calc.add(10)
calc.subtract(3)
print(calc.show()) # 7
# 方法链式调用——因为每个方法都返回 self
result = Calculator().add(10).subtract(3).add(5).show()
print(result) # 12
💡 链式调用的技巧: 方法返回
self 就可以连续调用了。很多 Python 库(如 pandas)大量使用这个模式。
4. 实例属性 vs 类属性
属性可以定义在实例上(每个对象独有),也可以定义在类上(所有对象共享):
PYTHON
class Student:
# 类属性——所有学生共享
school = "第一中学"
total_count = 0
def __init__(self, name):
# 实例属性——每个学生独有
self.name = name
Student.total_count += 1
s1 = Student("Alice")
s2 = Student("Bob")
# 类属性通过类名访问
print(Student.school) # 第一中学
print(Student.total_count) # 2
# 也可以通过实例访问(如果实例没有同名属性)
print(s1.school) # 第一中学
print(s2.school) # 第一中学
# 修改类属性会影响所有实例
Student.school = "第二中学"
print(s1.school) # 第二中学
▶ 示例:银行账户(难度⭐⭐)
PYTHON
class BankAccount:
"""银行账户"""
bank_name = "Python银行" # 类属性
interest_rate = 0.003 # 年利率 0.3%
def __init__(self, owner, balance=0):
self.owner = owner # 实例属性
self.balance = balance # 实例属性
def deposit(self, amount):
self.balance += amount
return f"存入{amount}元,余额{self.balance}元"
def withdraw(self, amount):
if amount > self.balance:
return "余额不足!"
self.balance -= amount
return f"取出{amount}元,余额{self.balance}元"
def yearly_interest(self):
"""计算年利息"""
interest = self.balance * BankAccount.interest_rate
return f"年利息:{interest:.2f}元"
acc1 = BankAccount("Alice", 10000)
acc2 = BankAccount("Bob", 5000)
print(acc1.deposit(5000)) # 存入5000元,余额15000元
print(acc2.withdraw(2000)) # 取出2000元,余额3000元
print(acc1.yearly_interest()) # 年利息:4.50元
# 所有账户共享利率
print(acc1.interest_rate) # 0.003
print(acc2.interest_rate) # 0.003
输出:
TEXT
📖 仅展示
# 函数定义成功
▶ 示例:学生成绩管理类(难度⭐⭐)
PYTHON
class Student:
"""学生类——带成绩管理方法"""
school = "编程学院"
total = 0
def __init__(self, name, student_id):
self.name = name
self.student_id = student_id
self.scores = {}
Student.total += 1
def add_score(self, subject, score):
"""添加一门课的成绩"""
self.scores[subject] = score
def average(self):
"""计算平均分"""
if not self.scores:
return 0
return sum(self.scores.values()) / len(self.scores)
def report(self):
"""生成成绩报告"""
lines = [f"学生:{self.name}({self.student_id})"]
for subj, sc in self.scores.items():
status = "及格" if sc >= 60 else "不及格"
lines.append(f" {subj}:{sc}分({status})")
lines.append(f" 平均分:{self.average():.1f}")
return "\n".join(lines)
s1 = Student("Alice", "001")
s1.add_score("语文", 85)
s1.add_score("数学", 72)
s1.add_score("英语", 90)
s2 = Student("Bob", "002")
s2.add_score("语文", 55)
s2.add_score("数学", 48)
print(s1.report())
print()
print(s2.report())
print(f"\n全校学生数:{Student.total}")
输出:
TEXT
📖 仅展示
学生:Alice(001)
语文:85分(及格)
数学:72分(及格)
英语:90分(及格)
平均分:82.3
学生:Bob(002)
语文:55分(不及格)
数学:48分(不及格)
平均分:51.5
全校学生数:2
5. 常见应用场景
- 数据建模:把现实事物映射成代码——用户、订单、商品等都用类表示。
- 状态管理:对象保存状态(属性),方法操作状态——如游戏角色、购物车。
- 代码组织:相关的数据和函数打包在一起,比散落的函数更清晰。
- 框架扩展:Django 的模型、Flask 的应用、GUI 的组件都是通过类实现的。
❓ 常见问题
Q 方法和函数有什么区别?
A 方法就是在类中定义的函数,第一个参数是
self。函数可以独立存在,方法必须通过对象或类调用。本质上方法也是函数,只是 Python 自动把调用者作为第一个参数传进去。Q 什么时候用类,什么时候用函数?
A 如果你需要维护状态(数据),用类——比如银行账户要记住余额。如果你只是做一次计算(输入→处理→输出),用函数——比如温度转换。一个简单的经验法则:如果只需要 1-2 个函数,用函数就够了;如果需要多个相关函数共享同一份数据,用类。
📖 小节
- 类(class)是模板,对象(object)是根据模板创建的具体实例
__init__是初始化方法,创建对象时自动调用- 方法的第一个参数是
self,代表当前对象 - 实例属性每个对象独有,类属性所有对象共享
- 类把数据和操作数据的方法打包在一起
📝 作业
-
基础题(难度⭐):定义一个
Car类,有brand、color、speed属性,有accelerate(value)加速方法和show_speed()显示速度的方法。 -
进阶题(难度⭐⭐):定义一个
Student类,用类属性统计学生总数,用实例属性记录每个学生的姓名和成绩。实现get_grade()方法返回等级(ABCD)。 -
挑战题(难度⭐⭐⭐):定义一个
Library类和Book类。Book有标题、作者、是否借出状态。Library有add_book(book)、borrow(title)、return_book(title)、show_books()四个方法。