从零开始学Python(九):面向对象编程

从零开始学Python(九):面向对象编程

本系列教程将带你从零开始学习Python编程,无需任何编程基础。

什么是面向对象编程?

面向对象编程(Object-Oriented Programming,OOP)是一种编程范式。它使用”对象”来设计软件。

类就像一张设计图纸或模板,对象是根据图纸制造的实际产品。例如”汽车设计图”是类,根据设计图生产的每一辆具体汽车是对象。

面向对象的好处是可以组织代码,将相关的数据和功能组合在一起,重用代码,创建类后可以多次使用,易于维护,修改类的实现不影响使用类的代码。

类和对象

使用 class 关键字定义类。创建对象称为实例化,使用类名加括号的方式。每个对象都有自己的属性值,但共享相同的方法。

类的组成部分

__init__ 方法是构造方法,创建对象时自动调用,用于初始化对象的属性。属性是对象的数据,使用self.属性名的方式定义和访问。方法是对象的行为(函数),定义时第一个参数必须是self,表示对象本身。

类属性和实例属性

类属性属于类本身,所有对象共享。实例属性属于每个对象,互不影响。类属性通常用于定义常量或共享数据,实例属性用于存储每个对象特有的数据。

继承

继承允许一个类获得另一个类的属性和方法。被继承的类称为父类或基类,继承的类称为子类或派生类。子类可以添加新的属性和方法,也可以重写父类的方法。

子类重写父类方法后,可以使用super()函数调用父类的方法。这在需要扩展而不是完全替换父类方法时很有用。

多态

多态允许不同类的对象对同一方法做出不同响应。这意味着可以编写通用的代码处理不同类型的对象,提高代码的灵活性和可扩展性。

实战示例:学生管理系统

让我们创建一个简单的学生管理系统,管理学生信息,包括本科生和研究生。

创建文件 student_system.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# 学生管理系统

from datetime import datetime

class Person:
"""人类(基类)"""
def __init__(self, name, age, id_number):
self.name = name
self.age = age
self.id_number = id_number

def introduce(self):
print(f"姓名:{self.name}")
print(f"年龄:{self.age}")
print(f"身份证号:{self.id_number}")

def __str__(self):
return f"{self.name}{self.age}岁)"


class Student(Person):
"""学生类"""
def __init__(self, name, age, id_number, student_id, major):
super().__init__(name, age, id_number)
self.student_id = student_id
self.major = major
self.courses = {} # 课程字典:{课程名: 分数}
self.enrollment_date = datetime.now()

def enroll_course(self, course_name):
"""选课"""
if course_name not in self.courses:
self.courses[course_name] = None
print(f"{self.name}成功选课:{course_name}")
else:
print(f"已经选过{course_name}了")

def set_score(self, course_name, score):
"""设置课程成绩"""
if course_name in self.courses:
if 0 <= score <= 100:
self.courses[course_name] = score
print(f"{course_name}成绩已设置为{score}分")
else:
print("成绩必须在0-100之间")
else:
print(f"未选{course_name}课程")

def get_gpa(self):
"""计算平均绩点"""
scores = [s for s in self.courses.values() if s is not None]
if not scores:
return 0.0
return sum(scores) / len(scores)

def introduce(self):
"""介绍自己"""
super().introduce()
print(f"学号:{self.student_id}")
print(f"专业:{self.major}")
print(f"已选课程:{len(self.courses)}门")
if self.courses:
print("课程成绩:")
for course, score in self.courses.items():
score_str = f"{score}分" if score is not None else "未出分"
print(f" - {course}{score_str}")
print(f"平均分:{self.get_gpa():.2f}")


class Undergraduate(Student):
"""本科生类"""
def __init__(self, name, age, id_number, student_id, major):
super().__init__(name, age, id_number, student_id, major)
self.degree = "本科"

def can_graduate(self):
"""检查是否可以毕业"""
completed = [s for s in self.courses.values() if s is not None and s >= 60]
return len(completed) >= 10 and self.get_gpa() >= 60

def introduce(self):
print("=" * 50)
print("【本科生信息】")
super().introduce()
print(f"学位:{self.degree}")
print(f"毕业状态:{'符合' if self.can_graduate() else '不符合'}条件")
print("=" * 50)


class Graduate(Student):
"""研究生类"""
def __init__(self, name, age, id_number, student_id, major, advisor):
super().__init__(name, age, id_number, student_id, major)
self.degree = "研究生"
self.advisor = advisor # 导师
self.research_topic = "" # 研究方向

def set_research_topic(self, topic):
"""设置研究方向"""
self.research_topic = topic
print(f"研究方向已设置为:{topic}")

def can_graduate(self):
"""检查是否可以毕业"""
completed = [s for s in self.courses.values() if s is not None and s >= 60]
return (len(completed) >= 6 and self.get_gpa() >= 75
and bool(self.research_topic))

def introduce(self):
print("=" * 50)
print("【研究生信息】")
super().introduce()
print(f"学位:{self.degree}")
print(f"导师:{self.advisor}")
print(f"研究方向:{self.research_topic or '未确定'}")
print(f"毕业状态:{'符合' if self.can_graduate() else '不符合'}条件")
print("=" * 50)


def main():
"""主程序"""
# 创建本科生
undergrad = Undergraduate(
name="张三",
age=20,
id_number="110101200301011234",
student_id="2023001",
major="计算机科学"
)

# 创建研究生
grad = Graduate(
name="李四",
age=25,
id_number="110101199801011234",
student_id="2023002",
major="人工智能",
advisor="王教授"
)

# 本科生选课和成绩
undergrad.enroll_course("Python编程")
undergrad.enroll_course("数据结构")
undergrad.enroll_course("算法分析")
undergrad.enroll_course("操作系统")
undergrad.set_score("Python编程", 85)
undergrad.set_score("数据结构", 78)
undergrad.set_score("算法分析", 92)
undergrad.set_score("操作系统", 88)
undergrad.introduce()

print()

# 研究生选课和成绩
grad.enroll_course("机器学习")
grad.enroll_course("深度学习")
grad.enroll_course("自然语言处理")
grad.set_research_topic("大语言模型")
grad.set_score("机器学习", 90)
grad.set_score("深度学习", 88)
grad.set_score("自然语言处理", 92)
grad.introduce()


if __name__ == "__main__":
main()

这个程序使用继承和多态组织代码。Person是基类包含通用的属性和方法,Student继承Person添加学生特有的属性和方法,Undergraduate和Graduate继承Student实现各自的毕业条件,使用super()调用父类方法,重写introduce()方法实现多态。

常见错误

定义方法时忘记self参数是最常见的错误。混淆类属性和实例属性可能导致意外的行为,实例属性会隐藏同名的类属性。不使用super()调用父类方法可能导致父类的初始化逻辑没有执行。


系列导航