类高级特性

深入探索Python类的魔法方法、元类、数据描述符等高级特性,构建强大的面向对象系统

魔法方法

元类

描述符

1. 魔法方法详解

魔法方法(Magic Methods)是以双下划线开头和结尾的特殊方法,它们让Python类能够支持内置操作。

小贴士:魔法方法让Python类更加Pythonic,能够自然地集成到Python生态系统中!

__init__ 和 __new__

class Person:
 def __new__(cls, name):
 print("创建实例")
 return super().__new__(cls)

 def __init__(self, name):
 print("初始化实例")
 self.name = name

__str__ 和 __repr__

class Book:
 def __init__(self, title, author):
 self.title = title
 self.author = author

 def __str__(self):
 return f"《{self.title}》- {self.author}"

 def __repr__(self):
 return f"Book('{self.title}', '{self.author}')"

__len__ 和 __getitem__

class ShoppingCart:
 def __init__(self):
 self.items = []

 def __len__(self):
 return len(self.items)

 def __getitem__(self, index):
 return self.items[index]

__call__ 方法

class Multiplier:
 def __init__(self, factor):
 self.factor = factor

 def __call__(self, value):
 return value * self.factor

完整示例:自定义列表类

class SmartList:
 """智能列表类,支持多种操作"""

 def __init__(self, items=None):
 self.items = items or []

 def __len__(self):
 return len(self.items)

 def __getitem__(self, index):
 return self.items[index]

 def __setitem__(self, index, value):
 self.items[index] = value

 def __delitem__(self, index):
 del self.items[index]

 def __iter__(self):
 return iter(self.items)

 def __contains__(self, item):
 return item in self.items

 def __add__(self, other):
 return SmartList(self.items + other.items)

 def __str__(self):
 return f"SmartList({self.items})"

 def __repr__(self):
 return f"SmartList({self.items})"

 def append(self, item):
 self.items.append(item)

 def extend(self, items):
 self.items.extend(items)

# 使用示例
numbers = SmartList([1, 2, 3])
print(len(numbers)) # 3
print(numbers[0]) # 1
numbers[0] = 10
print(numbers) # SmartList([10, 2, 3])
print(2 in numbers) # True

2. 属性描述符详解

描述符(Descriptor)是实现了特定协议的类,可以控制属性的访问、设置和删除。

注意事项:描述符是Python的高级特性,用于创建自定义的属性行为!

2.1 数据描述符

class ValidatedAttribute:
 """验证属性值的描述符"""

 def __init__(self, min_value=None, max_value=None):
 self.min_value = min_value
 self.max_value = max_value
 self._values = {}

 def __get__(self, instance, owner):
 if instance is None:
 return self
 return self._values.get(instance, None)

 def __set__(self, instance, value):
 if self.min_value is not None and value < self.min_value:
 raise ValueError(f"值必须大于等于 {self.min_value}")
 if self.max_value is not None and value > self.max_value:
 raise ValueError(f"值必须小于等于 {self.max_value}")
 self._values[instance] = value

 def __delete__(self, instance):
 if instance in self._values:
 del self._values[instance]

class Person:
 age = ValidatedAttribute(min_value=0, max_value=150)
 height = ValidatedAttribute(min_value=0, max_value=300)

# 使用示例
person = Person()
person.age = 25 # 正常
person.height = 175 # 正常
# person.age = -5 # 会抛出 ValueError

2.2 非数据描述符

class LazyProperty:
 """延迟计算属性描述符"""

 def __init__(self, func):
 self.func = func

 def __get__(self, instance, owner):
 if instance is None:
 return self
 value = self.func(instance)
 setattr(instance, self.func.__name__, value)
 return value

class Circle:
 def __init__(self, radius):
 self.radius = radius

 @LazyProperty
 def area(self):
 print("计算面积...")
 return 3.14159 * self.radius ** 2

# 使用示例
circle = Circle(5)
print(circle.area) # 第一次计算
print(circle.area) # 第二次直接使用缓存值

2.3 属性装饰器

class Temperature:
 """温度类,使用属性装饰器"""

 def __init__(self, celsius=0):
 self._celsius = celsius

 @property
 def celsius(self):
 """获取摄氏度"""
 return self._celsius

 @celsius.setter
 def celsius(self, value):
 """设置摄氏度"""
 if value < -273.15:
 raise ValueError("温度不能低于绝对零度")
 self._celsius = value

 @property
 def fahrenheit(self):
 """获取华氏度"""
 return self._celsius * 9/5 + 32

 @fahrenheit.setter
 def fahrenheit(self, value):
 """设置华氏度"""
 self.celsius = (value - 32) * 5/9

 @property
 def kelvin(self):
 """获取开尔文温度"""
 return self._celsius + 273.15

# 使用示例
temp = Temperature(25)
print(temp.celsius) # 25
print(temp.fahrenheit) # 77.0
print(temp.kelvin) # 298.15

temp.fahrenheit = 100
print(temp.celsius) # 37.77777777777778

3. 继承与多态高级

3.1 多重继承与MRO

class Animal:
 def speak(self):
 return "动物叫声"

class Flyer:
 def fly(self):
 return "我可以飞"

class Swimmer:
 def swim(self):
 return "我可以游泳"

class Duck(Animal, Flyer, Swimmer):
 def speak(self):
 return "嘎嘎"

 def __str__(self):
 return "鸭子"

# 使用示例
duck = Duck()
print(duck.speak()) # 嘎嘎
print(duck.fly()) # 我可以飞
print(duck.swim()) # 我可以游泳

# 查看方法解析顺序
print(Duck.__mro__)
# (, ,
# , , )

3.2 抽象基类

from abc import ABC, abstractmethod

class Shape(ABC):
 """抽象形状类"""

 @abstractmethod
 def area(self):
 """计算面积"""
 pass

 @abstractmethod
 def perimeter(self):
 """计算周长"""
 pass

 def __str__(self):
 return f"形状: {self.__class__.__name__}"

class Rectangle(Shape):
 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)

class Circle(Shape):
 def __init__(self, radius):
 self.radius = radius

 def area(self):
 return 3.14159 * self.radius ** 2

 def perimeter(self):
 return 2 * 3.14159 * self.radius

# 使用示例
shapes = [Rectangle(5, 3), Circle(4)]
for shape in shapes:
 print(f"{shape}: 面积={shape.area():.2f}, 周长={shape.perimeter():.2f}")

3.3 组合模式

class File:
 def __init__(self, name, size):
 self.name = name
 self.size = size

 def get_size(self):
 return self.size

class Directory:
 def __init__(self, name):
 self.name = name
 self.contents = []

 def add(self, item):
 self.contents.append(item)

 def remove(self, item):
 self.contents.remove(item)

 def get_size(self):
 return sum(item.get_size() for item in self.contents)

# 使用示例
root = Directory("根目录")
docs = Directory("文档")

docs.add(File("报告.txt", 1024))
docs.add(File("笔记.txt", 512))
root.add(docs)
root.add(File("程序.py", 2048))

print(f"总大小: {root.get_size()} 字节") # 3584

4. 元类基础

元类(Metaclass)是创建类的类,它们控制类的创建过程。

注意事项:元类是Python的极高阶特性,一般只在框架开发中使用!

4.1 简单元类

class SingletonMeta(type):
 """单例模式元类"""
 _instances = {}

 def __call__(cls, *args, **kwargs):
 if cls not in cls._instances:
 cls._instances[cls] = super().__call__(*args, **kwargs)
 return cls._instances[cls]

class DatabaseConnection(metaclass=SingletonMeta):
 def __init__(self):
 self.connection_id = id(self)
 print(f"创建数据库连接: {self.connection_id}")

# 使用示例
db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(db1 is db2) # True,只有一个实例

4.2 自动注册类

class AutoRegisterMeta(type):
 """自动注册类的元类"""
 registry = {}

 def __new__(cls, name, bases, attrs):
 new_class = super().__new__(cls, name, bases, attrs)
 cls.registry[name.lower()] = new_class
 return new_class

class BaseCommand(metaclass=AutoRegisterMeta):
 def execute(self):
 pass

class CreateCommand(BaseCommand):
 def execute(self):
 return "创建操作"

class DeleteCommand(BaseCommand):
 def execute(self):
 return "删除操作"

# 使用示例
print(AutoRegisterMeta.registry)
# {'basecommand': ,
# 'createcommand': ,
# 'deletecommand': }

故事化案例:智能游戏引擎

场景:小李是一名游戏开发者,正在开发一个复杂的角色扮演游戏。他需要创建一个灵活的游戏引擎,支持不同类型的游戏角色、装备系统和技能系统。让我们用类的高级特性来实现这个强大的游戏引擎!

1. 游戏角色系统

class CharacterMeta(type):
 """角色元类,自动注册角色类型"""

 def __new__(cls, name, bases, attrs):
 new_class = super().__new__(cls, name, bases, attrs)
 if not hasattr(cls, 'registry'):
 cls.registry = {}
 cls.registry[name.lower()] = new_class
 return new_class

class GameCharacter(metaclass=CharacterMeta):
 """游戏角色基类"""

 def __init__(self, name, level=1):
 self.name = name
 self.level = level
 self._health = 100
 self._mana = 50
 self._experience = 0

 @property
 def health(self):
 return self._health

 @health.setter
 def health(self, value):
 self._health = max(0, min(value, self.max_health))

 @property
 def mana(self):
 return self._mana

 @mana.setter
 def mana(self, value):
 self._mana = max(0, min(value, self.max_mana))

 @property
 def max_health(self):
 return 100 + self.level * 10

 @property
 def max_mana(self):
 return 50 + self.level * 5

 def __str__(self):
 return f"{self.__class__.__name__}: {self.name} (等级{self.level})"

 def __repr__(self):
 return f"{self.__class__.__name__}('{self.name}', {self.level})"

class Warrior(GameCharacter):
 def __init__(self, name, level=1):
 super().__init__(name, level)
 self.strength = 15 + level * 3
 self.defense = 12 + level * 2

 def attack(self):
 return f"{self.name} 使用剑击造成 {self.strength} 点伤害"

class Mage(GameCharacter):
 def __init__(self, name, level=1):
 super().__init__(name, level)
 self.intelligence = 18 + level * 4
 self.mana *= 1.5

 def cast_spell(self):
 if self.mana >= 20:
 self.mana -= 20
 return f"{self.name} 释放火球术造成 {self.intelligence * 1.5} 点魔法伤害"
 return f"{self.name} 魔力不足,无法施法"

class Archer(GameCharacter):
 def __init__(self, name, level=1):
 super().__init__(name, level)
 self.agility = 16 + level * 3.5
 self.critical_chance = 0.2 + level * 0.02

 def shoot_arrow(self):
 damage = self.agility * 1.2
 if random.random() < self.critical_chance:
 damage *= 2
 return f"{self.name} 射出暴击箭造成 {damage} 点伤害!"
 return f"{self.name} 射出箭矢造成 {damage} 点伤害"

# 使用示例
warrior = Warrior("亚瑟", 5)
mage = Mage("梅林", 4)
archer = Archer("罗宾", 3)

print(warrior)
print(mage)
print(archer)

print(CharacterMeta.registry)
# 查看所有注册的角色类型

2. 装备系统

class EquipmentMeta(type):
 """装备元类,管理装备类型"""

 def __new__(cls, name, bases, attrs):
 new_class = super().__new__(cls, name, bases, attrs)
 if not hasattr(cls, 'equipment_types'):
 cls.equipment_types = {}
 cls.equipment_types[name.lower()] = new_class
 return new_class

class Equipment(metaclass=EquipmentMeta):
 """装备基类"""

 def __init__(self, name, rarity="普通"):
 self.name = name
 self.rarity = rarity
 self._enhancement_level = 0

 @property
 def enhancement_level(self):
 return self._enhancement_level

 @enhancement_level.setter
 def enhancement_level(self, value):
 if 0 <= value <= 15:
 self._enhancement_level = value
 else:
 raise ValueError("强化等级必须在0-15之间")

 def __str__(self):
 rarity_colors = {
 "普通": "白色",
 "稀有": "蓝色",
 "史诗": "紫色",
 "传说": "橙色"
 }
 return f"{rarity_colors.get(self.rarity, '未知')} {self.rarity} {self.name} +{self.enhancement_level}"

 def __add__(self, other):
 """装备合成"""
 if isinstance(other, Equipment) and self.__class__ == other.__class__:
 new_name = f"强化{self.name}"
 new_equipment = self.__class__(new_name, self.rarity)
 new_equipment.enhancement_level = min(self.enhancement_level + 1, 15)
 return new_equipment
 raise TypeError("只能合成相同类型的装备")

class Weapon(Equipment):
 def __init__(self, name, attack_power, rarity="普通"):
 super().__init__(name, rarity)
 self.base_attack = attack_power
 self.weapon_type = "武器"

 @property
 def total_attack(self):
 return self.base_attack * (1 + self.enhancement_level * 0.1)

class Armor(Equipment):
 def __init__(self, name, defense_power, rarity="普通"):
 super().__init__(name, rarity)
 self.base_defense = defense_power
 self.armor_type = "防具"

 @property
 def total_defense(self):
 return self.base_defense * (1 + self.enhancement_level * 0.08)

class Accessory(Equipment):
 def __init__(self, name, special_effect, rarity="普通"):
 super().__init__(name, rarity)
 self.special_effect = special_effect
 self.accessory_type = "饰品"

# 使用示例
sword = Weapon("长剑", 100, "史诗")
shield = Armor("圆盾", 50, "稀有")
ring = Accessory("力量戒指", "增加10%攻击力")

print(sword)
print(shield)
print(ring)

# 装备合成
enhanced_sword = sword + sword
print(f"合成后: {enhanced_sword}")
print(f"攻击力: {enhanced_sword.total_attack}")

3. 技能系统

class SkillSystem:
 """技能系统管理器"""

 def __init__(self):
 self.skills = {}

 def register_skill(self, skill_class):
 """注册技能类"""
 self.skills[skill_class.__name__.lower()] = skill_class

 def create_skill(self, skill_name, *args, **kwargs):
 """创建技能实例"""
 if skill_name.lower() in self.skills:
 return self.skills[skill_name.lower()](*args, **kwargs)
 raise ValueError(f"未知技能: {skill_name}")

class Skill:
 """技能基类"""

 def __init__(self, name, mana_cost, cooldown):
 self.name = name
 self.mana_cost = mana_cost
 self.cooldown = cooldown
 self._current_cooldown = 0

 @property
 def is_ready(self):
 return self._current_cooldown <= 0

 def use(self, caster):
 """使用技能"""
 if not self.is_ready:
 return f"技能 {self.name} 冷却中 ({self._current_cooldown}回合)"

 if caster.mana < self.mana_cost:
 return f"魔力不足,无法使用 {self.name}"

 caster.mana -= self.mana_cost
 self._current_cooldown = self.cooldown
 return self.execute(caster)

 def execute(self, caster):
 """技能执行逻辑(子类实现)"""
 raise NotImplementedError

 def tick(self):
 """每回合更新"""
 if self._current_cooldown > 0:
 self._current_cooldown -= 1

class Fireball(Skill):
 def __init__(self):
 super().__init__("火球术", 20, 2)

 def execute(self, caster):
 damage = caster.intelligence * 1.5
 return f"{caster.name} 释放火球术造成 {damage} 点魔法伤害"

class Heal(Skill):
 def __init__(self):
 super().__init__("治疗术", 15, 3)

 def execute(self, caster):
 heal_amount = caster.intelligence * 2
 caster.health += heal_amount
 return f"{caster.name} 使用治疗术恢复 {heal_amount} 点生命值"

class Shield(Skill):
 def __init__(self):
 super().__init__("护盾术", 10, 4)

 def execute(self, caster):
 shield_amount = caster.defense * 1.2
 return f"{caster.name} 激活护盾,获得 {shield_amount} 点护盾值"

# 使用示例
skill_system = SkillSystem()
skill_system.register_skill(Fireball)
skill_system.register_skill(Heal)
skill_system.register_skill(Shield)

mage = Mage("艾莉娅", 10)
fireball = skill_system.create_skill("fireball")
heal = skill_system.create_skill("heal")

print(fireball.use(mage))
print(heal.use(mage))

# 模拟回合
for i in range(5):
 fireball.tick()
 if i == 2:
 print(fireball.use(mage)) # 冷却结束

高级练习题(共5个)

练习题1:观察者模式

使用描述符实现观察者模式,当对象属性发生变化时自动通知观察者。

# 参考答案
class Observable:
 def __init__(self):
 self._observers = []

 def add_observer(self, observer):
 self._observers.append(observer)

 def notify_observers(self, name, old_value, new_value):
 for observer in self._observers:
 observer.update(name, old_value, new_value)

class ObservableAttribute:
 def __init__(self, name):
 self.name = name
 self._values = {}

 def __get__(self, instance, owner):
 if instance is None:
 return self
 return self._values.get(instance, None)

 def __set__(self, instance, value):
 old_value = self._values.get(instance, None)
 self._values[instance] = value
 if hasattr(instance, 'notify_observers'):
 instance.notify_observers(self.name, old_value, value)

class GameCharacter(Observable):
 health = ObservableAttribute('health')
 mana = ObservableAttribute('mana')

 def __init__(self, name):
 super().__init__()
 self.name = name

class HealthBar:
 def update(self, name, old_value, new_value):
 if name == 'health':
 print(f"血量更新: {old_value} -> {new_value}")

# 使用示例
character = GameCharacter("英雄")
health_bar = HealthBar()
character.add_observer(health_bar)
character.health = 100
character.health = 80

练习题2:状态模式

实现状态模式,让游戏角色能够根据当前状态改变行为。

# 参考答案
class CharacterState:
 def handle_attack(self, character):
 pass

class NormalState(CharacterState):
 def handle_attack(self, character):
 return f"{character.name} 正常攻击"

class BuffedState(CharacterState):
 def handle_attack(self, character):
 return f"{character.name} 强化攻击造成双倍伤害"

class StunnedState(CharacterState):
 def handle_attack(self, character):
 return f"{character.name} 被眩晕,无法攻击"

class GameCharacter:
 def __init__(self, name):
 self.name = name
 self._state = NormalState()

 @property
 def state(self):
 return self._state

 @state.setter
 def state(self, new_state):
 self._state = new_state

 def attack(self):
 return self._state.handle_attack(self)

# 使用示例
character = GameCharacter("战士")
print(character.attack())
character.state = BuffedState()
print(character.attack())
character.state = StunnedState()
print(character.attack())

练习题3:策略模式

创建策略模式,让游戏角色能够动态切换战斗策略。

# 参考答案
from abc import ABC, abstractmethod

class AttackStrategy(ABC):
 @abstractmethod
 def calculate_damage(self, character):
 pass

class MeleeStrategy(AttackStrategy):
 def calculate_damage(self, character):
 return character.strength * 1.2

class MagicStrategy(AttackStrategy):
 def calculate_damage(self, character):
 return character.intelligence * 1.5

class RangedStrategy(AttackStrategy):
 def calculate_damage(self, character):
 return character.agility * 1.3

class GameCharacter:
 def __init__(self, name, strength=10, intelligence=10, agility=10):
 self.name = name
 self.strength = strength
 self.intelligence = intelligence
 self.agility = agility
 self.strategy = MeleeStrategy()

 def set_strategy(self, strategy):
 self.strategy = strategy

 def attack(self):
 damage = self.strategy.calculate_damage(self)
 return f"{self.name} 使用 {self.strategy.__class__.__name__} 造成 {damage} 点伤害"

# 使用示例
character = GameCharacter("英雄")
print(character.attack())
character.set_strategy(MagicStrategy())
print(character.attack())

练习题4:工厂模式

实现工厂模式,动态创建不同类型的游戏对象。

# 参考答案
class GameObjectFactory:
 _creators = {}

 @classmethod
 def register(cls, name):
 def decorator(creator_class):
 cls._creators[name] = creator_class
 return creator_class
 return decorator

 @classmethod
 def create(cls, name, *args, **kwargs):
 if name in cls._creators:
 return cls._creators[name](*args, **kwargs)
 raise ValueError(f"未知对象类型: {name}")

@GameObjectFactory.register("enemy")
class Enemy:
 def __init__(self, name, health):
 self.name = name
 self.health = health

@GameObjectFactory.register("item")
class Item:
 def __init__(self, name, value):
 self.name = name
 self.value = value

@GameObjectFactory.register("npc")
class NPC:
 def __init__(self, name, dialogue):
 self.name = name
 self.dialogue = dialogue

# 使用示例
enemy = GameObjectFactory.create("enemy", "哥布林", 50)
item = GameObjectFactory.create("item", "生命药水", 100)
npc = GameObjectFactory.create("npc", "村长", "欢迎来到村庄!")

练习题5:装饰器模式

实现装饰器模式,动态为游戏角色添加额外能力。

# 参考答案
class CharacterDecorator:
 def __init__(self, character):
 self.character = character

 def attack(self):
 return self.character.attack()

class FireEnchantDecorator(CharacterDecorator):
 def attack(self):
 base_attack = self.character.attack()
 return f"{base_attack} 并附加火焰伤害"

class IceEnchantDecorator(CharacterDecorator):
 def attack(self):
 base_attack = self.character.attack()
 return f"{base_attack} 并附加冰霜伤害"

class SpeedBoostDecorator(CharacterDecorator):
 def attack(self):
 base_attack = self.character.attack()
 return f"{base_attack} (速度提升)"

# 使用示例
warrior = Warrior("战士", 10)
decorated_warrior = FireEnchantDecorator(
 SpeedBoostDecorator(warrior)
)
print(decorated_warrior.attack())