🎯 高级魔法师实战:面向对象编程高级特性练习
📚 在本练习中,你将巩固Python面向对象编程的高级特性,包括类属性与实例属性、类方法与静态方法、私有属性、继承、多态、魔术方法等。通过实践,让你更深入地理解这些概念并能灵活运用。
🎯 练习目标
- 掌握类属性与实例属性的区别与使用场景
- 熟练使用类方法、静态方法和实例方法
- 理解并应用私有属性和属性访问控制
- 能够设计和实现类的继承关系
- 掌握多态的实际应用
- 了解并使用常用的魔术方法
- 能够创建和使用抽象基类
🏋️♂️ 基础练习题
1. 类属性与实例属性练习
任务: 创建一个 Student 类,包含以下内容:
- 类属性
total_students用于跟踪创建的学生总数 - 类属性
school_name设置为 "Python University" - 实例属性
name和student_id - 一个
display_info实例方法,打印学生的姓名、学号和学校名称
示例代码框架:
class Student:
# 在这里定义类属性
def __init__(self, name, student_id):
# 在这里定义实例属性
# 并更新类属性
def display_info(self):
# 打印学生信息测试代码:
# 创建学生实例
student1 = Student("张三", "2023001")
student2 = Student("李四", "2023002")
# 显示学生信息
student1.display_info()
student2.display_info()
# 显示总学生数和学校名称
print(f"总学生数: {Student.total_students}")
print(f"学校名称: {Student.school_name}")2. 类方法与静态方法练习
任务: 扩展上面的 Student 类,添加以下内容:
- 一个类方法
get_total_students,返回总学生数 - 一个类方法
change_school_name,修改学校名称 - 一个静态方法
validate_student_id,验证学生ID是否有效(假设有效格式为6位数字)
测试代码:
# 使用类方法
print(f"使用类方法获取总学生数: {Student.get_total_students()}")
Student.change_school_name("Python Institute")
student1.display_info() # 检查学校名称是否已更改
# 使用静态方法
print(f"2023001是否有效: {Student.validate_student_id('2023001')}")
print(f"ABC123是否有效: {Student.validate_student_id('ABC123')}")3. 私有属性与属性访问控制练习
任务: 创建一个 BankAccount 类,包含以下内容:
- 一个私有属性
_balance用于存储账户余额,初始值为0 - 一个
deposit方法,用于存款 - 一个
withdraw方法,用于取款(注意:余额不能为负) - 使用
@property装饰器创建一个只读的balance属性,用于查看当前余额 - 添加一个
@balance.setter装饰器,允许通过属性设置余额,但仍然进行验证
示例代码框架:
class BankAccount:
def __init__(self):
self._balance = 0
def deposit(self, amount):
# 实现存款功能
def withdraw(self, amount):
# 实现取款功能,确保余额不为负
@property
def balance(self):
# 返回当前余额
@balance.setter
def balance(self, amount):
# 设置余额,确保金额有效测试代码:
account = BankAccount()
account.deposit(1000)
print(f"当前余额: {account.balance}")
account.withdraw(500)
print(f"取款后余额: {account.balance}")
# account.withdraw(1000) # 这应该引发错误或提示
account.balance = 2000
print(f"设置后余额: {account.balance}")
# account.balance = -100 # 这应该引发错误或提示4. 继承练习
任务: 创建一个继承层次结构,表示不同类型的银行账户:
- 创建一个基础类
Account,包含账户持有者姓名和余额属性,以及存款和取款方法 - 创建两个子类:
SavingsAccount和CheckingAccount SavingsAccount应该有一个interest_rate属性和一个add_interest方法,用于计算和添加利息CheckingAccount应该有一个transaction_fee属性,并且取款时会收取费用
测试代码:
savings = SavingsAccount("王五", 1000, 0.05) # 5% 利率
checking = CheckingAccount("赵六", 1000, 2) # 2元交易费
savings.deposit(500)
savings.add_interest()
print(f"储蓄账户余额: {savings.balance}")
checking.withdraw(100)
print(f"支票账户余额: {checking.balance}")5. 魔术方法练习
任务: 创建一个 Book 类,实现以下魔术方法:
__init__: 初始化书名、作者和价格__str__: 返回书籍的可读字符串表示__repr__: 返回书籍的"官方"字符串表示__eq__: 比较两本书是否相同(基于书名和作者)__lt__: 基于价格比较两本书__add__: 实现两本书的"组合"(返回包含两本书的列表)
测试代码:
book1 = Book("Python编程", "张三", 99.0)
book2 = Book("Python高级编程", "李四", 129.0)
book3 = Book("Python编程", "张三", 99.0)
print(book1) # 测试 __str__
print(repr(book1)) # 测试 __repr__
print(book1 == book2) # 测试 __eq__
print(book1 == book3) # 测试 __eq__
print(book1 < book2) # 测试 __lt__
combined = book1 + book2 # 测试 __add__
print(f"组合结果: {combined}")🚀 挑战题
1. 图形类层次结构
任务: 创建一个图形类层次结构,包含抽象基类和具体实现类:
创建一个抽象基类
Shape,定义以下抽象方法:area(): 计算图形面积perimeter(): 计算图形周长display(): 显示图形信息
实现以下具体子类:
Rectangle: 矩形,需要 width 和 height 参数Circle: 圆形,需要 radius 参数Triangle: 三角形,需要 a, b, c 三个边长参数Polygon: 多边形,需要一个边长列表参数
创建一个
ShapeCollection类,用于管理多个图形对象:- 实现
add_shape方法添加图形 - 实现
total_area方法计算所有图形的总面积 - 实现
total_perimeter方法计算所有图形的总周长 - 实现
display_all方法显示所有图形的信息 - 实现
__len__魔术方法返回图形数量 - 实现
__getitem__魔术方法支持通过索引访问图形
- 实现
测试代码:
# 创建图形集合
shapes = ShapeCollection()
# 添加各种图形
shapes.add_shape(Rectangle(5, 3))
shapes.add_shape(Circle(4))
shapes.add_shape(Triangle(3, 4, 5))
shapes.add_shape(Polygon([3, 4, 5, 6]))
# 显示所有图形信息
shapes.display_all()
# 计算总面积和总周长
print(f"总面积: {shapes.total_area():.2f}")
print(f"总周长: {shapes.total_perimeter():.2f}")
print(f"图形数量: {len(shapes)}")
# 访问特定图形
first_shape = shapes[0]
print(f"第一个图形: {first_shape}")
print(f"第一个图形的面积: {first_shape.area():.2f}")2. 电子商务系统
任务: 创建一个简化的电子商务系统,包含以下类:
Product类:表示商品- 属性:
product_id,name,price,stock_quantity - 方法:
reduce_stock(quantity)减少库存 - 魔术方法:
__str__和__repr__
- 属性:
Customer类:表示顾客- 属性:
customer_id,name,email,address - 方法:
update_address(new_address)更新地址
- 属性:
Order类:表示订单- 属性:
order_id,customer,products(产品及其数量的字典),status,order_date - 方法:
add_product(product, quantity)添加产品 - 方法:
remove_product(product_id)移除产品 - 方法:
calculate_total()计算订单总金额 - 方法:
update_status(new_status)更新订单状态 - 魔术方法:
__str__
- 属性:
ShoppingCart类:表示购物车- 属性:
products(产品及其数量的字典) - 方法:
add_item(product, quantity)添加商品 - 方法:
remove_item(product_id)移除商品 - 方法:
update_quantity(product_id, quantity)更新商品数量 - 方法:
calculate_total()计算购物车总金额 - 方法:
checkout(customer)结账并创建订单 - 魔术方法:
__len__和__iter__(支持遍历购物车中的商品)
- 属性:
测试代码:
# 创建产品
product1 = Product(1, "Python编程书籍", 99.0, 100)
product2 = Product(2, "编程鼠标垫", 29.0, 200)
product3 = Product(3, "机械键盘", 499.0, 50)
# 创建顾客
customer = Customer(1, "张三", "zhangsan@example.com", "北京市海淀区")
# 创建购物车并添加商品
cart = ShoppingCart()
cart.add_item(product1, 2)
cart.add_item(product2, 3)
cart.add_item(product3, 1)
# 显示购物车信息
print(f"购物车商品数量: {len(cart)}")
print(f"购物车总金额: ¥{cart.calculate_total():.2f}")
# 遍历购物车商品
print("购物车中的商品:")
for item, quantity in cart:
print(f" {item.name}: {quantity}件")
# 更新商品数量
cart.update_quantity(2, 1)
print(f"更新后购物车总金额: ¥{cart.calculate_total():.2f}")
# 结账并创建订单
order = cart.checkout(customer)
print(f"订单创建成功: {order}")
print(f"订单总金额: ¥{order.calculate_total():.2f}")
# 检查产品库存
print(f"Python编程书籍剩余库存: {product1.stock_quantity}")💡 实践应用提示
设计类的层次结构时,先确定抽象基类,定义清晰的接口,然后再实现具体子类。
使用私有属性来保护内部状态,只提供必要的公共接口。
合理使用属性装饰器,可以在不改变接口的情况下,增加属性访问的控制逻辑。
遵循"组合优先于继承"原则,当不需要继承的全部功能时,考虑使用组合关系。
利用多态特性,可以编写更通用的代码,提高代码的可扩展性。
使用魔术方法可以使你的类与Python的内置功能更好地集成。
编写单元测试来验证你的类的行为是否符合预期。
📝 参考实现(部分)
以下是部分练习题的参考实现,供你完成练习后对照检查:
1. 类属性与实例属性练习参考实现
class Student:
# 类属性
total_students = 0
school_name = "Python University"
def __init__(self, name, student_id):
# 实例属性
self.name = name
self.student_id = student_id
# 更新类属性
Student.total_students += 1
def display_info(self):
print(f"姓名: {self.name}, 学号: {self.student_id}, 学校: {self.school_name}")2. 类方法与静态方法练习参考实现
class Student:
# 类属性
total_students = 0
school_name = "Python University"
def __init__(self, name, student_id):
self.name = name
self.student_id = student_id
Student.total_students += 1
def display_info(self):
print(f"姓名: {self.name}, 学号: {self.student_id}, 学校: {self.school_name}")
@classmethod
def get_total_students(cls):
return cls.total_students
@classmethod
def change_school_name(cls, new_name):
cls.school_name = new_name
@staticmethod
def validate_student_id(student_id):
return len(student_id) == 6 and student_id.isdigit()3. 私有属性与属性访问控制练习参考实现
class BankAccount:
def __init__(self):
self._balance = 0
def deposit(self, amount):
if amount > 0:
self._balance += amount
return f"存款成功,金额: ¥{amount}"
else:
return "存款金额必须为正数"
def withdraw(self, amount):
if amount <= 0:
return "取款金额必须为正数"
if amount > self._balance:
return "余额不足"
self._balance -= amount
return f"取款成功,金额: ¥{amount}"
@property
def balance(self):
return self._balance
@balance.setter
def balance(self, amount):
if amount < 0:
raise ValueError("余额不能为负数")
self._balance = amount完成这些练习后,你将对Python面向对象编程的高级特性有更深入的理解和应用能力。记得在实际项目中灵活运用这些知识,编写更加优雅、可维护的代码!💪 完成这些练习后,你将对Python面向对象编程的高级特性有更深入的理解和应用能力。记得在实际项目中灵活运用这些知识,编写更加优雅、可维护的代码!💪




