📝 第9天:面向对象编程高级特性魔法练习 - 魔法师的进阶实战训练
🎉 恭喜你完成了面向对象编程高级特性的学习!现在是时候通过一些有趣的练习来巩固你的知识了。这些练习将帮助你更好地理解和应用类方法、静态方法、属性装饰器、描述符、多重继承、元编程和反射等高级特性。
🎯 练习目标
- 熟练掌握类方法、静态方法和属性装饰器的使用
- 理解并应用描述符来定制属性访问行为
- 掌握多重继承和Mixin模式
- 了解元编程的基本概念和应用
- 能够使用反射机制在运行时操作对象
🔍 基础练习题
1. 温度转换器(属性装饰器练习)
任务: 创建一个Temperature类,使用属性装饰器实现摄氏度和华氏度之间的自动转换。
要求:
- 实现
celsius和fahrenheit两个属性,它们可以互相转换 - 当设置其中一个属性时,另一个属性会自动更新
- 添加适当的验证,确保温度值是有效的数字
示例:
python
temp = Temperature(celsius=25)
print(temp.celsius) # 输出: 25.0
print(temp.fahrenheit) # 输出: 77.0
temp.fahrenheit = 98.6
print(temp.celsius) # 输出: 37.0
print(temp.fahrenheit) # 输出: 98.62. 商品库存管理(类方法练习)
任务: 创建一个Product类,使用类方法来跟踪和管理所有产品的库存。
要求:
- 实现类变量来跟踪所有产品的总数
- 创建类方法来获取产品总数、查找产品和更新库存
- 实现实例方法来增加或减少单个产品的库存
示例:
python
Product.add_product("手机", 100, 2999.0)
Product.add_product("笔记本电脑", 50, 5999.0)
print(f"总产品数: {Product.get_total_products()}")
product = Product.find_product("手机")
if product:
product.reduce_stock(10)
print(f"手机剩余库存: {product.stock}")3. 验证器描述符(描述符练习)
任务: 创建几个描述符类来验证不同类型的属性。
要求:
- 实现
StringValidator、NumberValidator和EmailValidator描述符 - 每个描述符应该能够验证属性值是否符合特定的规则
- 在一个
User类中使用这些描述符
示例:
python
class User:
username = StringValidator("username", min_length=3, max_length=20)
age = NumberValidator("age", min_value=18, max_value=120)
email = EmailValidator("email")
def __init__(self, username, age, email):
self.username = username
self.age = age
self.email = email
user = User("john_doe", 25, "john.doe@example.com")
# user.username = "j" # 会引发ValueError异常
# user.age = 16 # 会引发ValueError异常
# user.email = "invalid-email" # 会引发ValueError异常4. 动物模拟器(多重继承练习)
任务: 创建一个动物模拟器,使用多重继承来组合不同的特性。
要求:
- 创建基础的
Animal类和几个特性类(如CanFly,CanSwim,CanWalk) - 通过多重继承创建具有多种特性的具体动物类(如
Bird可以飞和走,Duck可以飞、走和游) - 确保方法解析顺序正确工作
示例:
python
bird = Bird("麻雀")
bird.fly() # 输出: 麻雀正在飞行
bird.walk() # 输出: 麻雀正在走路
duck = Duck("鸭子")
duck.fly() # 输出: 鸭子正在飞行
duck.walk() # 输出: 鸭子正在走路
duck.swim() # 输出: 鸭子正在游泳5. 反射式配置管理器(反射练习)
任务: 创建一个配置管理器,可以使用反射机制动态地设置和获取配置项。
要求:
- 实现
ConfigManager类,使用反射来管理配置项 - 提供方法来设置、获取、检查和删除配置项
- 支持从字典加载配置和导出配置到字典
示例:
python
config = ConfigManager()
config.set_config("database.url", "mongodb://localhost:27017")
config.set_config("database.username", "admin")
config.set_config("database.password", "password")
print(f"数据库URL: {config.get_config('database.url')}")
print(f"是否存在API密钥配置: {config.has_config('api.key')}")
# 导出配置到字典
config_dict = config.export_config()
print(f"配置字典: {config_dict}")🚀 挑战题
1. 高级计算器(综合练习)
任务: 创建一个高级计算器,结合多种面向对象编程高级特性。
要求:
- 使用Mixin模式添加日志、错误处理等功能
- 使用描述符验证输入参数
- 使用类方法实现常用的计算功能
- 使用属性装饰器实现计算结果的缓存
提示:
- 创建
Calculator基类,实现基本的计算功能 - 创建
LoggingMixin、ErrorHandlingMixin等Mixin类 - 创建
NumberValidator描述符来验证输入参数 - 使用
@property装饰器实现结果缓存
2. ORM框架简化版(元编程练习)
任务: 创建一个简化版的ORM(对象关系映射)框架,使用元编程来动态创建模型类。
要求:
- 实现一个
Model基类,使用元类来处理表名、字段等信息 - 实现字段描述符(如
StringField,IntegerField,FloatField)来定义表的列 - 提供基本的CRUD(创建、读取、更新、删除)操作
- 支持简单的查询条件
提示:
- 使用元类来拦截模型类的创建过程,收集字段信息
- 实现字段描述符来处理字段值的存储和检索
- 提供方法来将模型对象转换为数据库记录,以及从数据库记录创建模型对象
💡 部分参考答案
1. 温度转换器参考答案
python
class Temperature:
def __init__(self, celsius=None, fahrenheit=None):
if celsius is not None:
self._celsius = float(celsius)
elif fahrenheit is not None:
self._celsius = (float(fahrenheit) - 32) * 5 / 9
else:
raise ValueError("必须提供摄氏度或华氏度值")
@property
def celsius(self):
return self._celsius
@celsius.setter
def celsius(self, value):
try:
self._celsius = float(value)
except (TypeError, ValueError):
raise ValueError("温度必须是有效的数字")
@property
def fahrenheit(self):
return self._celsius * 9 / 5 + 32
@fahrenheit.setter
def fahrenheit(self, value):
try:
self._celsius = (float(value) - 32) * 5 / 9
except (TypeError, ValueError):
raise ValueError("温度必须是有效的数字")2. 商品库存管理参考答案
python
class Product:
_products = {}
_total_count = 0
def __init__(self, name, stock, price):
self.name = name
self.stock = stock
self.price = price
@classmethod
def add_product(cls, name, stock, price):
"""添加新商品"""
if name in cls._products:
raise ValueError(f"商品'{name}'已存在")
product = cls(name, stock, price)
cls._products[name] = product
cls._total_count += 1
return product
@classmethod
def get_total_products(cls):
"""获取商品总数"""
return cls._total_count
@classmethod
def find_product(cls, name):
"""查找商品"""
return cls._products.get(name)
def increase_stock(self, amount):
"""增加库存"""
if amount < 0:
raise ValueError("增加的数量不能为负数")
self.stock += amount
def reduce_stock(self, amount):
"""减少库存"""
if amount < 0:
raise ValueError("减少的数量不能为负数")
if amount > self.stock:
raise ValueError("库存不足")
self.stock -= amount3. 验证器描述符参考答案
python
class StringValidator:
def __init__(self, name, min_length=0, max_length=None):
self.name = name
self.min_length = min_length
self.max_length = max_length
def __get__(self, instance, owner):
if instance is None:
return self
return instance.__dict__.get(self.name, "")
def __set__(self, instance, value):
if not isinstance(value, str):
raise TypeError(f"{self.name}必须是字符串类型")
if len(value) < self.min_length:
raise ValueError(f"{self.name}长度不能小于{self.min_length}")
if self.max_length is not None and len(value) > self.max_length:
raise ValueError(f"{self.name}长度不能大于{self.max_length}")
instance.__dict__[self.name] = value
class NumberValidator:
def __init__(self, name, min_value=None, max_value=None):
self.name = name
self.min_value = min_value
self.max_value = max_value
def __get__(self, instance, owner):
if instance is None:
return self
return instance.__dict__.get(self.name, 0)
def __set__(self, instance, value):
try:
value = float(value)
except (TypeError, ValueError):
raise TypeError(f"{self.name}必须是数字类型")
if self.min_value is not None and value < self.min_value:
raise ValueError(f"{self.name}不能小于{self.min_value}")
if self.max_value is not None and value > self.max_value:
raise ValueError(f"{self.name}不能大于{self.max_value}")
instance.__dict__[self.name] = value
class EmailValidator:
def __init__(self, name):
self.name = name
def __get__(self, instance, owner):
if instance is None:
return self
return instance.__dict__.get(self.name, "")
def __set__(self, instance, value):
if not isinstance(value, str):
raise TypeError(f"{self.name}必须是字符串类型")
if "@" not in value:
raise ValueError(f"{self.name}不是有效的邮箱地址")
instance.__dict__[self.name] = value
class User:
username = StringValidator("username", min_length=3, max_length=20)
age = NumberValidator("age", min_value=18, max_value=120)
email = EmailValidator("email")
def __init__(self, username, age, email):
self.username = username
self.age = age
self.email = email4. 动物模拟器参考答案
python
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print(f"{self.name} 发出了声音")
class CanFly:
def fly(self):
print(f"{self.name} 正在飞行")
class CanSwim:
def swim(self):
print(f"{self.name} 正在游泳")
class CanWalk:
def walk(self):
print(f"{self.name} 正在走路")
class Bird(Animal, CanFly, CanWalk):
def speak(self):
print(f"{self.name} 叽叽喳喳地叫")
class Fish(Animal, CanSwim):
def speak(self):
print(f"{self.name} 没有发出声音")
class Duck(Animal, CanFly, CanSwim, CanWalk):
def speak(self):
print(f"{self.name} 呱呱地叫")5. 反射式配置管理器参考答案
python
class ConfigManager:
def __init__(self):
self._config = {}
def set_config(self, key, value):
"""设置配置项"""
# 支持嵌套配置,如 "database.url"
parts = key.split(".")
config = self._config
# 遍历除最后一个部分外的所有部分
for part in parts[:-1]:
if part not in config or not isinstance(config[part], dict):
config[part] = {}
config = config[part]
# 设置最后一个部分的值
config[parts[-1]] = value
def get_config(self, key, default=None):
"""获取配置项"""
parts = key.split(".")
config = self._config
# 遍历所有部分
for part in parts:
if part not in config or not isinstance(config, dict):
return default
config = config[part]
return config
def has_config(self, key):
"""检查配置项是否存在"""
parts = key.split(".")
config = self._config
# 遍历所有部分
for part in parts:
if part not in config or not isinstance(config, dict):
return False
config = config[part]
return True
def remove_config(self, key):
"""删除配置项"""
parts = key.split(".")
config = self._config
parents = []
# 遍历所有部分并记录父配置
for part in parts[:-1]:
if part not in config or not isinstance(config, dict):
return False
parents.append((config, part))
config = config[part]
# 删除配置项
if parts[-1] in config:
del config[parts[-1]]
# 清理空的父配置
for parent, part in reversed(parents):
if not parent[part]:
del parent[part]
return True
return False
def export_config(self):
"""导出配置到字典"""
return self._config.copy()
def load_config(self, config_dict):
"""从字典加载配置"""
# 递归地将字典中的所有配置项添加到配置管理器中
def _load_dict(prefix, d):
for key, value in d.items():
full_key = f"{prefix}.{key}" if prefix else key
if isinstance(value, dict):
_load_dict(full_key, value)
else:
self.set_config(full_key, value)
_load_dict("", config_dict)🎯 练习总结
通过这些练习,你应该能够:
- 熟练使用类方法、静态方法和属性装饰器来增强类的功能
- 理解并应用描述符来自定义属性访问行为
- 掌握多重继承和Mixin模式来组合不同的功能
- 了解元编程的基本概念和应用
- 使用反射机制在运行时操作对象
这些高级特性可以帮助你编写更加灵活、可维护和可扩展的代码。在实际项目中,合理地运用这些特性可以大大提高代码的质量和效率。
继续加油!下一课我们将学习Python的模块和包管理,敬请期待!🚀




