人狗大战Ⅱ:融合了封装、继承、多态、鸭子类型、类属性 / 方法、静态方法、特殊方法、super、property、抽象基类、__slots__等语法特性
以下是一个稍微复杂的 “人狗大战” 面向对象实现,融合了封装、继承、多态、鸭子类型、类属性 / 方法、静态方法、特殊方法、super、property、slots 等语法特性,并在注释中详细说明:
from abc import ABC, abstractmethod # 抽象基类,用于定义接口约束
import random
# 1. 抽象基类:定义所有战斗角色的接口(封装核心行为)
class Fighter(ABC):
# 类属性:记录所有战斗角色的总数(类级别的状态)
total_fighters = 0
def __init__(self, name: str, hp: int, attack: int):
self._name = name # 单下划线:约定为内部属性,通过property暴露
self._hp = hp # 生命值,私有属性通过property控制访问
self._attack = attack # 基础攻击力
Fighter.total_fighters += 1 # 每次实例化,总数+1
# 用property装饰器封装属性访问,实现数据校验(封装的核心)
@property
def name(self) -> str:
return self._name
@property
def hp(self) -> int:
return self._hp
@hp.setter
def hp(self, value: int):
# 确保生命值不会为负(封装的保护作用)
self._hp = max(0, value)
# 抽象方法:所有战斗角色必须实现攻击逻辑(多态的基础)
@abstractmethod
def attack(self, enemy: 'Fighter') -> None:
pass
# 特殊方法:自定义打印格式(增强可读性)
def __str__(self) -> str:
return f"{self.name}(生命值:{self.hp},攻击力:{self._attack})"
# 特殊方法:定义对象的布尔值(用于判断是否存活)
def __bool__(self) -> bool:
return self.hp > 0
# 类方法:获取当前战斗角色总数(操作类属性)
@classmethod
def get_total_count(cls) -> int:
return cls.total_fighters
# 静态方法:判断是否触发暴击(纯工具逻辑,无状态依赖)
@staticmethod
def is_critical() -> bool:
return random.random() < 0.3 # 30%暴击概率
# 2. 人类角色:继承自Fighter,实现具体战斗逻辑
class Human(Fighter):
# __slots__:限制实例可添加的属性,节省内存并防止误添加
__slots__ = ('_name', '_hp', '_attack', '_weapon')#全是私有属性
def __init__(self, name: str, hp: int = 100, attack: int = 25, weapon: str = "拳头"):
# 调用父类构造方法(super的典型应用)
super().__init__(name, hp, attack)
self._weapon = weapon # 武器类型
# 重写攻击方法:实现人类特有的攻击逻辑(多态体现)
def attack(self, enemy: Fighter) -> None:
if not self: # 利用__bool__判断自身是否存活
print(f"{self.name}已倒下,无法攻击!")
return
# 基础伤害
damage = self._attack
# 武器加成:武器伤害翻倍(封装的保护作用)
if self._weapon == "武器":
damage *= 2
# 暴击判定(调用父类静态方法)
if Fighter.is_critical():
damage *= 2
crit_msg = "(暴击!)"
else:
crit_msg = ""
# 应用伤害(通过property修改hp,触发数据校验)
enemy.hp -= damage
print(f"{self.name}用{self._weapon}攻击了{enemy.name},造成{damage}点伤害{crit_msg}!{enemy.name}剩余{enemy.hp}血")
# 人类特有方法:使用药品回血
def use_medicine(self, value: int) -> None:
self.hp += value # 通过property修改,确保不会溢出(虽然此处未限制上限)
print(f"{self.name}使用药品回血{value}点,当前生命值:{self.hp}")
# 3. 狗类角色:继承自Fighter,实现不同攻击逻辑(多态)
class Dog(Fighter):
__slots__ = ('_name', '_hp', '_attack', '_breed') # 限制属性
def __init__(self, name: str, breed: str, hp: int = 80, attack: int = 20):
super().__init__(name, hp, attack)
self._breed = breed # 狗的品种
# 重写攻击方法:狗的攻击逻辑(多态体现)
def attack(self, enemy: Fighter) -> None:
if not self:
print(f"{self.name}已倒下,无法攻击!")
return
damage = self._attack
# 品种加成:藏獒有额外伤害
if self._breed == "藏獒":
damage += 10
enemy.hp -= damage
print(f"{self.name}({self._breed})撕咬了{enemy.name},造成{damage}点伤害!{enemy.name}剩余{enemy.hp}血")
# 狗特有方法:吠叫(威慑敌人)
def bark(self) -> None:
print(f"{self.name}发出凶狠的叫声:汪汪!{enemy.name}感到害怕!" if 'enemy' in locals() else f"{self.name}汪汪叫!")
# 4. 机器人角色:无继承Fighter,但实现了attack和hp属性(鸭子类型)
class Robot:
"""机器人:未继承Fighter,但有attack方法和hp属性,可参与战斗(鸭子类型)"""
def __init__(self, name: str, hp: int = 150, attack: int = 30):
self.name = name
self.hp = hp # 直接公开属性(对比Fighter的封装)
self.attack_power = attack
def attack(self, enemy: Fighter) -> None:
if self.hp <= 0:
print(f"{self.name}已瘫痪,无法攻击!")
return
damage = self.attack_power * 1.5 # 机器人攻击有稳定加成
enemy.hp -= damage
print(f"{self.name}发射激光攻击{enemy.name},造成{int(damage)}点伤害!{enemy.name}剩余{enemy.hp}血")
# 实现__bool__,与Fighter保持一致的布尔判断逻辑
def __bool__(self) -> bool:
return self.hp > 0
def __str__(self) -> str:
return f"{self.name}(机器人,生命值:{self.hp},攻击力:{self.attack_power})"
# 5. 战斗管理器:负责组织战斗流程、执行战斗、管理战斗角色
class BattleManager:
def __init__(self, fighters):# 初始化战斗管理器,接收Fighter和Robot列表
self.fighters = fighters # 战斗角色列表(支持Fighter和Robot,体现鸭子类型)
# 执行回合制战斗
def start_battle(self, rounds: int = 3) -> None:
print("=== 战斗开始 ===")
for i in range(1, rounds + 1):
print(f"\n----- 第{i}回合 -----")
# 遍历所有角色,让存活的角色随机攻击另一个存活角色
for attacker in self.fighters:
if not attacker: # 利用__bool__判断是否存活
continue
# 筛选存活的敌人(排除自己)
enemies = [f for f in self.fighters if f != attacker and f]
if enemies:
target = random.choice(enemies)
attacker.attack(target) # 多态调用:不同角色攻击逻辑不同
print("\n=== 战斗结束 ===")
# 打印存活角色
survivors = [f for f in self.fighters if f]
print(f"存活角色:{', '.join(str(f) for f in survivors)}")
# 6. 主程序:初始化角色并开始战斗
if __name__ == "__main__":
# 创建战斗角色(人类、狗、机器人)
human = Human("小明", hp=120, attack=30, weapon="火箭弹")
dog1 = Dog("旺财", breed="藏獒", hp=100, attack=25)
dog2 = Dog("小白", breed="京巴", hp=70, attack=15)
robot = Robot("终结者T800", hp=200, attack=35)
# 打印初始角色信息
print("初始角色:")
print(human, dog1, dog2, robot, sep="\n")
print(f"当前Fighter总数:{Fighter.get_total_count()}(人类和狗属于Fighter子类,机器人属于Robot类)")
# 人类使用药品(特有方法)
human.use_medicine(30)
# 狗吠叫(特有方法)
dog1.bark()
# 初始化战斗管理器并开始战斗
battle = BattleManager([human, dog1, dog2, robot])
battle.start_battle(rounds=4) # 进行4回合战斗
代码中用到的面向对象语法总结:
封装:通过 property 控制属性访问(如 hp 的读写校验)、单下划线约定内部属性、slots 限制属性添加;
继承:Human 和 Dog 继承 Fighter 基类,复用属性和方法;
多态:Human、Dog、Robot 都实现 attack 方法,通过同一调用 attacker.attack(target) 触发不同逻辑;
鸭子类型:Robot 未继承 Fighter,但因有 attack 和 hp 可参与战斗;
类属性 / 方法:Fighter.total_fighters 统计总数,get_total_count 访问类属性;
静态方法:Fighter.is_critical 实现暴击判定(无状态依赖);
特殊方法:str 自定义打印、bool 定义存活判断;
抽象基类(ABC):Fighter 用 @abstractmethod 强制子类实现 attack;
super 函数:子类构造方法中调用父类 init;
关联模式:BattleManager 关联多个 Fighter 管理战斗流程。
通过这些特性,代码既保证了逻辑的清晰性,又具备良好的扩展性(如新增 “猫” 角色只需实现 attack 方法即可加入战斗)。

浙公网安备 33010602011771号