🏰 第9天:魔法学院高级咒语研修班:面向对象编程高级特性
🧙♂️ 欢迎回来,年轻的魔法师!在前一节课中,我们学习了面向对象编程的基础咒语。今天,我们将进入霍格沃茨的禁书区,探索Python中面向对象编程的高级魔法!这些强大的咒语将让你的代码更加灵活、强大,甚至能够创造出自己的魔法生物!
🧪 魔法学习目标
🎯 掌握高级魔法咒语:类方法、静态方法和属性装饰器 🛡️ 理解魔法结界:属性访问控制机制 🪄 学习变形术的精髓:描述符的概念和使用 ✨ 探索创造世界的奥秘:元编程的基础概念 🧩 掌握复合魔法:多重继承和Mixin模式 🔮 学习心灵感应术:Python中的反射机制
🧠 魔法知识小调查
在开始今天的高级魔法学习之前,让我们快速测试一下你对面向对象编程基础的掌握程度:
- 在Python中,如何创建一个类?
- 什么是实例方法?它的第一个参数是什么?
- 什么是继承?如何在Python中实现继承?
- 什么是
__init__方法?它的作用是什么? - 如何重写父类的方法?
如果你对这些问题还不太确定,建议先复习上一节课的内容,然后再继续我们的高级魔法之旅!
🎭 魔法师小剧场:咒语的选择
场景:霍格沃茨魔法学院的课堂上
邓布利多教授:(挥舞魔杖) "同学们,今天我们要学习三种不同类型的魔法咒语。让我们先来区分一下它们的用途..."
哈利:"教授,为什么我们需要三种不同的咒语?它们不都是执行任务的吗?"
邓布利多教授:"问得好,哈利!想象一下,如果你需要施展一个影响整个学院的魔法,一个只与特定魔法理论相关的魔法,或者一个只针对你自己物品的魔法。它们的施法方式和影响范围都会不同..."
让我们开始学习这三种强大的高级魔法咒语!
🔧 高级魔法咒语:类方法、静态方法和属性装饰器
在Python的魔法世界里,除了普通的实例方法咒语外,还有三种强大的高级魔法:类方法、静态方法和属性装饰器。它们分别通过@classmethod、@staticmethod和@property魔法符文来激活。
1. 学院魔法(类方法,Class Method)
学院魔法是绑定到整个魔法学院(类)而不是单个魔法师(实例)的咒语。它可以访问和修改学院的共享资源。类方法的第一个参数是cls,代表魔法学院本身。
适用场景:
- 当需要访问或修改学院的共享资源时
- 当需要创建学院的魔法师,但不需要访问魔法师的个人物品时
- 当需要定义一个与学院相关的通用魔法时
示例咒语:
class 霍格沃茨学院:
学生总数 = 0 # 学院共享资源,用于跟踪学生数量
def __init__(self, 姓名, 学院):
self.姓名 = 姓名
self.学院 = 学院
霍格沃茨学院.学生总数 += 1 # 每录取一名学生,总数加1
@classmethod
def 获取学生总数(cls):
return cls.学生总数
@classmethod
def 录取学生(cls, 录取通知书):
# 从录取通知书创建学生的工厂方法
姓名, 学院 = 录取通知书.split(",")
return cls(姓名, 学院)
# 录取学生
哈利 = 霍格沃茨学院("哈利·波特", "格兰芬多")
赫敏 = 霍格沃茨学院("赫敏·格兰杰", "格兰芬多")
# 通过学院调用类方法
print(f"霍格沃茨目前共有 {霍格沃茨学院.获取学生总数()} 名学生") # 输出: 霍格沃茨目前共有 2 名学生
# 通过学生调用类方法
print(f"霍格沃茨目前共有 {哈利.获取学生总数()} 名学生") # 输出: 霍格沃茨目前共有 2 名学生
# 使用工厂方法录取学生
马尔福 = 霍格沃茨学院.录取学生("德拉科·马尔福,斯莱特林")
print(f"霍格沃茨目前共有 {霍格沃茨学院.获取学生总数()} 名学生") # 输出: 霍格沃茨目前共有 3 名学生
print(f"新录取学生: {马尔福.姓名},来自{马尔福.学院}") # 输出: 新录取学生: 德拉科·马尔福,来自斯莱特林2. 通用魔法(静态方法,Static Method)
通用魔法是一种特殊的魔法,它既不绑定到学院也不绑定到魔法师,任何有魔法天赋的人都可以使用。它不接收特殊的第一个参数(如self或cls),相当于独立的魔法咒语。
适用场景:
- 当需要定义一个与魔法相关但不依赖于学院或魔法师状态的通用魔法时
- 当魔法咒语内部不使用
self或cls参数时
示例咒语:
class 魔法数学:
@staticmethod
def 魔法加法(a, b):
return a + b
@staticmethod
def 魔法乘法(a, b):
return a * b
@staticmethod
def 是偶数(number):
return number % 2 == 0
# 直接使用通用魔法
结果1 = 魔法数学.魔法加法(5, 3)
结果2 = 魔法数学.魔法乘法(4, 6)
print(f"5 + 3 = {结果1}") # 输出: 5 + 3 = 8
print(f"4 * 6 = {结果2}") # 输出: 4 * 6 = 24
print(f"10是否为偶数: {魔法数学.是偶数(10)}") # 输出: 10是否为偶数: True
# 也可以通过魔法师调用通用魔法(但不推荐)
赫敏的魔法书 = 魔法数学()
print(f"15是否为偶数: {赫敏的魔法书.是偶数(15)}") # 输出: 15是否为偶数: False3. 隐形魔法(属性装饰器,Property Decorator)
@property是一种强大的隐形魔法,它可以将方法伪装成属性,让你可以像访问属性一样调用方法,而不需要使用括号。这种魔法常用于保护重要的魔法秘密或实现计算属性。
适用场景:
- 当需要控制对重要魔法秘密的访问时
- 当需要定义一个计算属性时(该属性的值是根据其他属性动态计算的)
示例咒语:
class 魔法药水:
def __init__(self, 原材料重量):
self._原材料重量 = 原材料重量 # 使用下划线表示这是一个内部秘密
@property
def 原材料重量(self):
"""获取药水的原材料重量"""
return self._原材料重量
@原材料重量.setter
def 原材料重量(self, value):
"""设置药水的原材料重量,确保重量为正数"""
if value > 0:
self._原材料重量 = value
else:
raise ValueError("原材料重量必须为正数")
@property
def 魔法强度(self):
"""计算药水的魔法强度(只读属性)"""
return self._原材料重量 * 10 # 假设每克原材料提供10点魔法强度
@property
def 持续时间(self):
"""计算药水的持续时间(只读属性)"""
return self._原材料重量 * 2 # 假设每克原材料提供2分钟持续时间
# 制作一瓶魔法药水
隐形药水 = 魔法药水(5)
# 访问魔法属性(实际上调用的是方法)
print(f"原材料重量: {隐形药水.原材料重量} 克") # 输出: 原材料重量: 5 克
print(f"魔法强度: {隐形药水.魔法强度}") # 输出: 魔法强度: 50
print(f"持续时间: {隐形药水.持续时间} 分钟") # 输出: 持续时间: 10 分钟
# 修改原材料重量(实际上调用的是setter方法)
隐形药水.原材料重量 = 10
print(f"新的原材料重量: {隐形药水.原材料重量} 克") # 输出: 新的原材料重量: 10 克
print(f"新的魔法强度: {隐形药水.魔法强度}") # 输出: 新的魔法强度: 100
# 尝试设置无效的原材料重量(会引发ValueError异常)
# 隐形药水.原材料重量 = -5
# 尝试修改只读属性(会引发AttributeError异常)
# 隐形药水.魔法强度 = 200🛡️ 魔法结界:高级封装与属性访问控制
在魔法世界中,保护重要的魔法秘密是至关重要的。Python提供了多种魔法结界来保护你的魔法属性,除了前面介绍的属性装饰器外,还有以下几种特殊的魔法方法可以用来定制属性访问行为。
1. 属性守卫(__getattr__, __setattr__, __delattr__)
这三个特殊魔法可以用来守护你的魔法属性,拦截对它们的访问、修改和删除操作。
__getattr__(self, name): 当有魔法师尝试访问一个不存在的魔法属性时激活__setattr__(self, name, value): 当有魔法师尝试设置魔法属性时激活(无论属性是否存在)__delattr__(self, name): 当有魔法师尝试删除魔法属性时激活
示例魔法结界:
class 魔法日志守卫:
def __init__(self):
self._魔法物品 = {} # 存储所有的魔法物品
def __getattr__(self, name):
"""当访问不存在的魔法物品时激活"""
if name in self._魔法物品:
return self._魔法物品[name]
else:
print(f"⚠️ 警告: 尝试访问不存在的魔法物品 '{name}'")
return None
def __setattr__(self, name, value):
"""当设置魔法物品时激活"""
if name == "_魔法物品":
# 直接设置内部魔法物品库,避免无限递归
super().__setattr__(name, value)
else:
print(f"✨ 设置魔法物品 '{name}' = {value}")
self._魔法物品[name] = value
def __delattr__(self, name):
"""当删除魔法物品时激活"""
if name == "_魔法物品":
super().__delattr__(name)
elif name in self._魔法物品:
print(f"🔥 删除魔法物品 '{name}'")
del self._魔法物品[name]
else:
print(f"⚠️ 警告: 尝试删除不存在的魔法物品 '{name}'")
# 创建魔法日志守卫
守卫 = 魔法日志守卫()
# 设置魔法物品
守卫.魔法书 = "标准咒语,初级版"
守卫.魔杖 = "凤凰羽毛芯,冬青木"
# 访问存在的魔法物品
print(f"魔法书: {守卫.魔法书}")
# 访问不存在的魔法物品
print(f"飞天扫帚: {守卫.飞天扫帚}")
# 删除魔法物品
del 守卫.魔杖
# 尝试删除不存在的魔法物品
del 守卫.隐形斗篷2. 终极守卫(__getattribute__)
__getattribute__魔法是一种更强大的守卫,它在每次有魔法师访问你的魔法属性时都会被激活,无论该属性是否存在。它比__getattr__具有更高的优先级。
注意:在__getattribute__魔法中,应该使用super().__getattribute__(name)来获取属性的值,否则会导致无限递归。
示例终极守卫:
class 秘密宝库守卫:
def __init__(self):
self.公共物品 = "这是一个公共的魔法物品"
self._受保护物品 = "这是一个受保护的魔法物品"
self.__秘密物品 = "这是一个高度机密的魔法物品"
def __getattribute__(self, name):
"""每次访问魔法物品时都会激活"""
if name.startswith("__") and not name.endswith("__"):
# 拦截对秘密物品的直接访问
raise AttributeError(f"🚫 不允许直接访问秘密物品 '{name}'")
# 使用super()获取物品,避免无限递归
return super().__getattribute__(name)
# 创建秘密宝库守卫
宝库守卫 = 秘密宝库守卫()
# 访问公共物品
print(宝库守卫.公共物品)
# 访问受保护物品
print(宝库守卫._受保护物品)
# 尝试访问秘密物品(会引发AttributeError异常)
# print(宝库守卫.__秘密物品)
# 可以通过名称修饰后的名称访问秘密物品(不推荐)
print(宝库守卫._秘密宝库守卫__秘密物品)🔍 变形术:描述符(Descriptors)
描述符是变形术的精髓所在,它是一种实现了__get__、__set__或__delete__方法的魔法对象,用于定制属性访问行为。掌握了描述符,你就可以让你的魔法属性拥有神奇的变形能力!
1. 描述符的定义
一个类只要实现了__get__、__set__或__delete__魔法方法中的至少一个,就可以被称为描述符。
- 数据描述符(Data Descriptor):同时实现了
__get__和__set__方法的描述符,具有更强大的变形能力 - 非数据描述符(Non-data Descriptor):只实现了
__get__方法的描述符,变形能力相对较弱
示例变形术:
class 正数变形术:
def __init__(self, name):
self.name = name
def __get__(self, instance, owner):
if instance is None:
return self
return instance.__dict__.get(self.name, 0)
def __set__(self, instance, value):
if value < 0:
raise ValueError("❌ 魔法值必须为正数!")
instance.__dict__[self.name] = value
class 魔法城堡:
# 使用描述符定义魔法属性
高度 = 正数变形术("height")
宽度 = 正数变形术("width")
def __init__(self, 高度, 宽度):
self.高度 = 高度 # 会调用正数变形术的__set__方法
self.宽度 = 宽度 # 会调用正数变形术的__set__方法
@property
def 面积(self):
return self.高度 * self.宽度 # 会调用正数变形术的__get__方法
# 创建魔法城堡
城堡 = 魔法城堡(10, 20)
print(f"城堡高度: {城堡.高度}, 城堡宽度: {城堡.宽度}, 城堡面积: {城堡.面积}")
# 修改魔法属性值
城堡.高度 = 15
print(f"修改后 - 城堡高度: {城堡.高度}, 城堡面积: {城堡.面积}")
# 尝试设置无效的属性值(会引发ValueError异常)
# 城堡.宽度 = -52. 描述符的应用场景
描述符常用于:
- 属性验证和类型检查(如确保魔法值为正数)
- 属性的计算和转换(如将普通数字转换为魔法能量值)
- 惰性计算(延迟计算,保存魔法能量)
- 属性访问控制(保护重要的魔法秘密)
示例:使用描述符实现惰性魔法计算
class 惰性魔法计算:
def __init__(self, func):
self.func = func
self.name = func.__name__
def __get__(self, instance, owner):
if instance is None:
return self
# 计算魔法值
value = self.func(instance)
# 缓存计算结果,下次直接返回(节省魔法能量)
instance.__dict__[self.name] = value
return value
class 魔法水晶球:
def __init__(self, 半径):
self.半径 = 半径
@惰性魔法计算 # 使用描述符装饰方法
def 魔法能量(self):
print("🔮 正在聚集魔法能量计算...")
import math
return math.pi * self.半径 ** 2 * 1000 # 假设魔法能量与水晶球体积成正比
# 创建魔法水晶球
水晶球 = 魔法水晶球(5)
# 第一次访问魔法能量属性(会计算)
print(f"魔法能量: {水晶球.魔法能量:.2f}")
# 第二次访问魔法能量属性(直接返回缓存的结果)
print(f"魔法能量: {水晶球.魔法能量:.2f}")🧩 复合魔法:多重继承与Mixin模式
在魔法世界中,最强大的魔法师往往掌握着多种不同派系的魔法。Python支持多重继承,让你的类可以同时学习多个父类的魔法。不过,这种强大的力量也伴随着一定的复杂性,需要谨慎使用。
1. 多重继承的基本咒语
class 复合魔法师(派系1, 派系2, 派系3):
# 魔法师定义
pass2. 魔法继承顺序(MRO)
Python使用C3算法来解决多重继承中的魔法继承顺序问题。可以通过__mro__属性或mro()方法来查看类的魔法继承顺序。
示例魔法继承顺序:
class 基础魔法:
def 施展魔法(self):
print("✨ 施展基础魔法")
class 攻击魔法(基础魔法):
def 施展魔法(self):
print("⚔️ 施展攻击魔法")
class 防御魔法(基础魔法):
def 施展魔法(self):
print("🛡️ 施展防御魔法")
class 复合魔法师(攻击魔法, 防御魔法):
pass
# 查看复合魔法师的魔法继承顺序
print(复合魔法师.__mro__)
# 输出: (<class '__main__.复合魔法师'>, <class '__main__.攻击魔法'>, <class '__main__.防御魔法'>, <class '__main__.基础魔法'>, <class 'object'>)
# 创建复合魔法师
哈利 = 复合魔法师()
哈利.施展魔法() # 输出: ⚔️ 施展攻击魔法 (因为攻击魔法在防御魔法前面)
# 调用特定派系的魔法
super(攻击魔法, 哈利).施展魔法() # 输出: 🛡️ 施展防御魔法 (super(攻击魔法, 哈利)会调用防御魔法的方法)
super(防御魔法, 哈利).施展魔法() # 输出: ✨ 施展基础魔法 (super(防御魔法, 哈利)会调用基础魔法的方法)3. Mixin魔法模式
Mixin是一种特殊的多重继承方式,它是一种小型的、专注于某一特定功能的魔法派系,用于增强其他魔法师的能力。Mixin类通常不单独使用,而是与其他类一起继承。
Mixin魔法的特点:
- 通常不包含个人物品(即没有
__init__方法或实例变量) - 只提供魔法技能来增强能力
- 命名通常以"Mixin"结尾
示例Mixin魔法:
# 定义Mixin魔法派系
class 飞行魔法Mixin:
def 飞行(self):
print("🧹 骑上飞天扫帚,飞向天空!")
class 隐形魔法Mixin:
def 隐形(self):
print(" invisibility cloak activated! 隐形斗篷已激活!")
# 使用Mixin魔法增强能力
class 高级魔法师(飞行魔法Mixin, 隐形魔法Mixin):
def __init__(self, 姓名):
self.姓名 = 姓名
def 介绍(self):
print(f"我是高级魔法师{self.姓名}!")
# 创建高级魔法师
哈利 = 高级魔法师("哈利·波特")
哈利.介绍() # 输出: 我是高级魔法师哈利·波特!
哈利.飞行() # 输出: 🧹 骑上飞天扫帚,飞向天空!
哈利.隐形() # 输出: invisibility cloak activated! 隐形斗篷已激活!🔮 创世魔法:元编程(Metaprogramming)基础
元编程是最强大、最神秘的魔法之一,它允许你编写能够创造和修改其他魔法的魔法。在Python中,元编程主要通过元类(Metaclass)来实现。元类是创造类的类,它可以控制类的创造过程。
1. 什么是元类?
在Python的魔法世界里,一切都是魔法生物,类也是一种特殊的魔法生物。而元类就是创造这些类生物的生物。默认情况下,Python中的类都是由type元类创造的。
# 检查类的类型
class 我的魔法:
pass
print(type(我的魔法)) # 输出: <class 'type'>
print(type(int)) # 输出: <class 'type'>
print(type(str)) # 输出: <class 'type'>2. 使用type动态创造类
type魔法不仅可以用来检查魔法生物的类型,还可以用来动态创造新的魔法生物。
咒语语法:type(name, bases, attrs)
name: 类名(魔法生物的名字)bases: 父类元组(魔法生物的祖先)attrs: 类属性和方法的字典(魔法生物的能力和特征)
示例创世魔法:
# 使用type动态创造一个魔法师类
def 施展咒语(self):
print(f"🧙♂️ 魔法师{self.name}施展了一个强大的咒语!")
# 创造一个魔法师类,继承自object,包含name属性和施展咒语方法
魔法师 = type("魔法师", (object,), {
"name": "未知魔法师",
"施展咒语": 施展咒语
})
# 创造魔法师实例
甘道夫 = 魔法师()
甘道夫.name = "甘道夫"
甘道夫.施展咒语() # 输出: 🧙♂️ 魔法师甘道夫施展了一个强大的咒语!3. 自定义元类
自定义元类可以让你完全控制类的创造过程,例如修改类的属性、添加方法、验证类的定义等。这是一种极其强大的魔法,需要谨慎使用。
示例自定义元类:
class 魔法日志元类(type):
def __new__(mcs, name, bases, attrs):
# 在创造类之前添加魔法日志
print(f"✨ 正在创造魔法生物 '{name}'")
# 为每个魔法技能添加日志功能
for attr_name, attr_value in list(attrs.items()):
if callable(attr_value) and not attr_name.startswith("__"):
# 保存原始魔法技能
original_method = attr_value
# 定义包装魔法
def wrapper(self, *args, **kwargs):
print(f"🪄 正在准备 '{attr_name}' 魔法...")
result = original_method(self, *args, **kwargs)
print(f"💥 '{attr_name}' 魔法释放完成!")
return result
# 替换原始魔法技能
attrs[attr_name] = wrapper
# 创造类
return super().__new__(mcs, name, bases, attrs)
# 使用自定义元类
class 魔法生物(metaclass=魔法日志元类):
def 火球术(self):
print("🔥 火球术:一个巨大的火球飞向目标!")
return "火球术成功"
def 冰冻术(self):
print("❄️ 冰冻术:目标被冻成冰块!")
return "冰冻术成功"
# 创造魔法生物实例
龙 = 魔法生物()
# 释放魔法(会显示魔法准备和释放的过程)
结果 = 龙.火球术() # 输出: 🪄 正在准备 '火球术' 魔法... 和 🔥 火球术:一个巨大的火球飞向目标! 和 💥 '火球术' 魔法释放完成!
print(f"魔法结果: {结果}") # 输出: 魔法结果: 火球术成功🔄 心灵感应:反射(Reflection)机制
反射是一种心灵感应魔法,它允许你在运行时感知和操作魔法生物的思想和能力。在Python中,反射机制主要通过内置魔法函数和特殊属性来实现。
1. 常用的反射魔法
getattr(object, name[, default]): 读取魔法生物的思想(获取属性或方法)setattr(object, name, value): 修改魔法生物的思想(设置属性或方法)hasattr(object, name): 探测魔法生物是否有某种能力(检查是否有指定的属性或方法)delattr(object, name): 删除魔法生物的某种能力(删除属性或方法)dir([object]): 全面扫描魔法生物的所有能力(获取对象的所有属性和方法名称)type(object): 识别魔法生物的种族(获取对象的类型)isinstance(object, classinfo): 判断魔法生物是否属于某个种族(检查对象是否是指定类或其子类的实例)
示例心灵感应魔法:
class 巫师:
def __init__(self, name, age):
self.name = name
self.age = age
def 施法(self):
print(f"🧙♂️ {self.name}正在施法!")
def 过生日(self):
self.age += 1
print(f"🎂 生日快乐!现在{self.name}已经{self.age}岁了。")
# 创造巫师实例
赫敏 = 巫师("赫敏·格兰杰", 17)
# 检查巫师是否有某种能力
print(f"赫敏会施法吗? {hasattr(赫敏, '施法')}") # 输出: True
print(f"赫敏会飞吗? {hasattr(赫敏, '飞行')}") # 输出: False
# 读取巫师的思想
print(f"巫师的名字: {getattr(赫敏, 'name')}") # 输出: 赫敏·格兰杰
# 读取不存在的思想(使用默认值)
宠物 = getattr(赫敏, '宠物', '未知')
print(f"巫师的宠物: {宠物}") # 输出: 未知
# 修改巫师的思想
setattr(赫敏, '宠物', '克鲁克山')
print(f"修改后巫师的宠物: {赫敏.宠物}") # 输出: 克鲁克山
# 命令巫师施展魔法
if hasattr(赫敏, '施法'):
getattr(赫敏, '施法')() # 输出: 🧙♂️ 赫敏·格兰杰正在施法!
# 全面扫描巫师的所有能力
print(f"巫师的能力清单: {dir(赫敏)}")
# 识别巫师的种族
print(f"这是什么种族? {type(赫敏)}") # 输出: <class '__main__.巫师'>
print(f"这是巫师吗? {isinstance(赫敏, 巫师)}") # 输出: True
print(f"这是魔法生物吗? {isinstance(赫敏, object)}") # 输出: True2. 反射的应用场景
反射常用于:
- 动态加载魔法卷轴和魔法生物(动态加载模块和类)
- 魔法插件系统的实现
- 魔法生物的变形和重塑(序列化和反序列化对象)
- 魔法框架的开发
示例:使用反射创造魔法命令系统
class 魔法命令大师:
def __init__(self):
self.魔法咒语 = {
"问候": self.问候,
"加法": self.加法,
"离开": self.离开
}
def 问候(self, name):
print(f"👋 你好,{name}!欢迎来到魔法世界!")
def 加法(self, a, b):
result = int(a) + int(b)
print(f"🧮 {a} + {b} = {result}")
def 离开(self):
print("👋 再见!欢迎再次来到魔法世界!")
return False
def 处理命令(self, 咒语):
parts = 咒语.strip().split()
if not parts:
return True
魔法名称 = parts[0]
魔法参数 = parts[1:]
if 魔法名称 in self.魔法咒语:
# 使用反射调用对应的魔法
魔法 = self.魔法咒语[魔法名称]
return 魔法(*魔法参数) if 魔法名称 != "离开" else 魔法()
else:
print(f"❓ 未知魔法: {魔法名称}")
return True
# 创造魔法命令大师
邓布利多 = 魔法命令大师()
# 简单的魔法命令界面
def 魔法命令界面():
print("🧙♂️ 欢迎使用魔法命令系统!")
print("可用命令: 问候 <名字>, 加法 <a> <b>, 离开")
运行中 = True
while 运行中:
咒语 = input("请输入魔法咒语: ")
运行中 = 邓布利多.处理命令(咒语)
# 如果直接运行此魔法卷轴,则启动魔法命令界面
if __name__ == "__main__":
魔法命令界面()🎮 高级魔法实践:创造你的专属魔法师
任务:创建一个名为魔法师的类,包含以下高级魔法特性:
- 使用属性装饰器实现对姓名、年龄和魔杖的访问控制
- 姓名不能为空,年龄必须在0到200之间,魔杖必须包含特定材质
- 实现一个
__str__方法,返回格式化的魔法师信息 - 使用反射机制获取和设置魔法师的属性
- 添加一个类方法来统计当前有多少魔法师存在
魔法卷轴框架:
class 魔法师:
魔法师总数 = 0 # 类变量,用于统计魔法师总数
def __init__(self, name, age, wand):
self.name = name # 使用属性装饰器
self.age = age # 使用属性装饰器
self.wand = wand # 使用属性装饰器
魔法师.魔法师总数 += 1 # 每创建一个魔法师,总数加1
@property
def name(self):
# 实现getter方法
pass
@name.setter
def name(self, value):
# 实现setter方法,验证姓名不能为空
pass
# 类似地实现age和wand的属性装饰器
@classmethod
def 获取魔法师总数(cls):
# 返回当前魔法师总数
pass
def __str__(self):
# 返回格式化的魔法师信息
pass
# 测试代码
哈利 = 魔法师("哈利·波特", 17, "凤凰羽毛芯,冬青木")
赫敏 = 魔法师("赫敏·格兰杰", 17, "龙心弦,葡萄藤木")
print(哈利)
print(f"当前魔法师总数: {魔法师.获取魔法师总数()}")
# 使用反射机制获取和设置属性
print(f"姓名: {getattr(哈利, 'name')}")
setattr(哈利, 'age', 18)
print(f"新年龄: {哈利.age}")挑战升级:添加一个静态方法来验证魔杖的材质是否合法,并在属性装饰器中调用它。
🧠 魔法师小测试
以下哪种魔法是通过
@classmethod符文激活的? A. 个人魔法(实例方法) B. 学院魔法(类方法) C. 通用魔法(静态方法) D. 隐形魔法(属性装饰器)使用
@property装饰器的作用是什么? A. 将方法伪装成属性,像访问属性一样调用方法 B. 让方法只能通过类调用 C. 让方法可以被所有魔法生物使用 D. 让方法具有特殊的变形能力什么是描述符(Descriptor)? A. 一种特殊的魔法咒语 B. 实现了
__get__、__set__或__delete__方法的魔法对象 C. 一种特殊的元类 D. 一种用于创造类的魔法Python使用什么算法来解决多重继承中的魔法继承顺序问题? A. BFS算法 B. DFS算法 C. C3算法 D. KMP算法
以下哪个不是Python反射机制的内置函数? A.
getattr()B.setattr()C.hasattr()D.creatattr()
📝 今日魔法总结
今天我们学习了Python中面向对象编程的高级魔法,包括:
高级魔法咒语:
- 学院魔法(类方法)通过
@classmethod符文激活,访问学院共享资源 - 通用魔法(静态方法)通过
@staticmethod符文激活,与学院和魔法师状态无关 - 隐形魔法(属性装饰器)通过
@property符文激活,控制属性访问
- 学院魔法(类方法)通过
魔法结界:
- 使用
__getattr__、__setattr__和__delattr__守护魔法属性 - 使用
__getattribute__拦截所有魔法属性访问
- 使用
变形术(描述符):
- 实现了
__get__、__set__或__delete__方法的魔法对象 - 用于定制属性访问行为,赋予属性变形能力
- 实现了
复合魔法(多重继承与Mixin模式):
- 一个魔法师可以学习多种不同派系的魔法
- 使用Mixin模式增强魔法师的特定能力
创世魔法(元编程基础):
- 使用元类控制类的创造过程
- 使用
type动态创造新的魔法生物
心灵感应(反射机制):
- 在运行时感知和操作魔法生物的思想和能力
- 通过内置魔法函数实现反射
这些高级魔法可以帮助你编写更加灵活、可维护和可扩展的代码。通过不断地练习和实践,你将能够更加熟练地运用这些魔法来解决实际问题。
下一节课,我们将学习Python的模块和包管理,探索如何组织和分享你的魔法卷轴!🚀




