课程 20:类(Class)
1. 类与对象基础
1.1 类和对象
类(Class): 就像是一个模板或蓝图,定义了某种事物的共同特征和行为。
对象(Object): 是根据类创建的具体实例,就像用模板制作出来的具体物品。
生活中的例子:
• 类:汽车设计图(定义汽车有轮子、发动机、能行驶等)
• 对象:具体的汽车(如我的红色宝马、你的白色丰田)
编程中的例子:
• 类:Student(定义学生有姓名、成绩、能显示信息等)
• 对象:具体的学生(如张三、李四等)
1.2 类的定义与实例化
# 定义类和创建对象
class Student: # 定义类:Student 是类名
def __init__(self, name, score): # 构造方法:创建对象时自动调用
self.name = name # 实例属性:每个对象独有的数据
self.score = score # 实例属性:每个对象独有的数据
def show_info(self): # 实例方法:对象的行为
print(f"学生姓名:{self.name},成绩:{self.score}")
def get_grade(self): # 实例方法:根据成绩返回等级
if self.score >= 90:
return "优秀"
elif self.score >= 80:
return "良好"
elif self.score >= 60:
return "及格"
else:
return "不及格"
# 创建对象:stu 是 Student 类的实例
stu = Student('Alice', 95) # 调用构造方法,传入参数 'Alice' 和 95
print(stu.name, stu.score) # 访问对象的属性
stu.show_info() # 调用对象的方法
print(f"等级:{stu.get_grade()}") # 调用方法并获取返回值
常用术语:
• 属性:对象的数据(如name、score)
• 方法:对象的行为(如show_score)
• 构造函数:__init__,用于初始化对象
• 析构函数:__del__,对象销毁时自动调用
2. 属性与方法细化
2.1 实例属性、类属性、私有属性
class Student:
school = 'YunfanEdu' # 类属性:所有实例共享,属于类本身
def __init__(self, name, score):
self.name = name # 实例属性:每个对象独有的数据
self._secret = '私有数据' # 约定私有属性:下划线开头,约定为内部使用
# 创建对象
stu = Student('Bob', 88)
# 访问实例属性和类属性
print(stu.name, stu.school) # 访问实例属性和类属性
print(stu._secret) # 不建议外部访问私有属性
2.2 方法类型:实例方法、类方法、静态方法
class Demo:
def instance_method(self): # 实例方法:需要self参数,通过对象调用
print('实例方法')
@classmethod # 装饰器:标记为类方法
def class_method(cls): # 类方法:需要cls参数,通过类调用
print('类方法')
@staticmethod # 装饰器:标记为静态方法
def static_method(): # 静态方法:不需要self或cls,通过类调用
print('静态方法')
# 创建对象
d = Demo()
# 调用实例方法:需要对象
d.instance_method() # 通过对象调用实例方法
# 调用类方法:通过类名调用
Demo.class_method() # 通过类调用类方法
# 调用静态方法:通过类名调用
Demo.static_method() # 通过类调用静态方法
2.3 属性封装与getter/setter
class Person:
def __init__(self, age):
self._age = age # 私有属性:用下划线开头,约定为内部使用
@property # 装饰器:将方法转换为属性(getter)
def age(self): # getter方法:获取属性值
return self._age
@age.setter # 装饰器:设置属性的setter方法
def age(self, value): # setter方法:设置属性值,可以添加验证
if value < 0:
raise ValueError('年龄不能为负') # 数据验证:防止无效数据
self._age = value
# 创建对象
p = Person(18) # 初始化年龄为18
# 使用属性:看起来像普通属性,实际调用了方法
p.age = 20 # 调用setter方法,设置年龄为20
print(p.age) # 调用getter方法,获取年龄值
建议: 用@property保护属性安全,便于后期维护和扩展。
3. 魔法方法与调试技巧
3.1 __str__、__repr__、__eq__等
class Student:
def __init__(self, name, score):
self.name = name
self.score = score
def __str__(self): # 魔法方法:定义对象的字符串表示(用户友好)
return f"Student({self.name}, {self.score})"
def __eq__(self, other): # 魔法方法:定义对象相等性比较
return self.name == other.name and self.score == other.score
# 创建两个相同的学生对象
stu1 = Student('Alice', 95)
stu2 = Student('Alice', 95)
# 测试魔法方法
print(stu1) # 调用__str__方法,输出友好的字符串表示
print(stu1 == stu2) # 调用__eq__方法,比较两个对象是否相等
调试技巧: __str__和__repr__便于打印对象,__eq__等便于对象比较。
4. 继承、多态、组合与高级OOP
4.1 继承与super()
class Animal: # 父类(基类)
def speak(self):
print('动物叫')
class Dog(Animal): # 子类:继承父类Animal
def speak(self): # 重写父类方法
super().speak() # 调用父类方法
print('汪汪!') # 添加子类特有的行为
# 创建子类对象
d = Dog()
d.speak() # 调用重写后的方法
4.2 多态与鸭子类型
class Cat: # 另一个类,也有speak方法
def speak(self):
print('喵喵!')
def animal_speak(animal): # 多态函数:接受任何有speak方法的对象
animal.speak() # 调用对象的speak方法
# 多态演示:不同对象调用相同接口,产生不同结果
for a in [Dog(), Cat()]: # 创建不同类型的对象
animal_speak(a) # 多态:同一函数处理不同类型对象
4.3 组合与MRO
class Engine: # 发动机类
def start(self):
print('发动机启动')
class Car: # 汽车类
def __init__(self):
self.engine = Engine() # 组合:汽车包含发动机对象
def drive(self):
self.engine.start() # 通过组合对象调用方法
print('汽车行驶')
# 创建汽车对象
car = Car()
car.drive() # 调用汽车方法,内部使用发动机
# 查看方法解析顺序(MRO)
print(Car.__mro__) # 显示类的继承顺序
OOP进阶: 组合优于继承,MRO(方法解析顺序)影响多重继承下方法调用。
5. 类的实际应用案例
5.1 学生成绩管理
class Student:
def __init__(self, name):
self.name = name
self.scores = {} # 用字典存储多门课程成绩
def add_score(self, subject, score): # 添加成绩方法
self.scores[subject] = score
def show_all(self): # 显示所有成绩方法
print(f"{self.name}的成绩:")
for subject, score in self.scores.items():
print(f" {subject}: {score}")
# 创建学生对象并管理成绩
stu = Student('Alice')
stu.add_score('Math', 95) # 添加数学成绩
stu.add_score('English', 88) # 添加英语成绩
stu.show_all() # 显示所有成绩
5.2 银行账户与工厂模式
class Account: # 银行账户类
def __init__(self, owner, balance=0):
self.owner = owner # 账户持有人
self.balance = balance # 账户余额
def deposit(self, amount): # 存款方法
self.balance += amount
def withdraw(self, amount): # 取款方法
if amount > self.balance:
print('余额不足')
else:
self.balance -= amount
class AccountFactory: # 工厂类:负责创建账户对象
@staticmethod
def create_account(owner): # 静态方法:创建账户
return Account(owner)
# 使用工厂模式创建账户
acc = AccountFactory.create_account('Tom')
acc.deposit(100) # 存款100
print(acc.balance) # 查看余额
5.3 图形类与方法扩展
class Rectangle: # 矩形类
def __init__(self, width, height):
self.width = width # 宽度
self.height = height # 高度
def area(self): # 计算面积方法
return self.width * self.height
def perimeter(self): # 计算周长方法
return 2 * (self.width + self.height)
def is_square(self): # 判断是否为正方形方法
return self.width == self.height
# 创建矩形对象并测试方法
rect = Rectangle(3, 4)
print('面积:', rect.area()) # 计算并输出面积
print('周长:', rect.perimeter()) # 计算并输出周长
print('是否正方形:', rect.is_square()) # 判断并输出是否为正方形
实际应用: 类常用于建模现实世界对象、管理数据、实现复杂逻辑、封装第三方库、设计模式等。
学习建议:类是OOP的基础,建议多动手实践,理解属性、方法、继承、多态、组合、设计模式等核心概念,遇到报错要学会调试和查文档。推荐多用__str__/__repr__、isinstance、UML等工具辅助调试和设计。
思考题:类和对象的区别是什么?如何设计一个高内聚、低耦合的类?OOP有哪些常见误区,如何避免?组合和继承如何选择?UML类图在设计中的作用?