AI for Youth Academy 青少年AI研究计划

第一年 · 第14周

第十四章:队伍、列表、循环和你自己的类

上周你为对象添加了方法——attack、heal、show_stats。本周你将把这些对象放入列表、循环遍历队伍、运行一场完整的战斗。然后在第五课时,你将从零开始设计属于你自己的类。

第四课时:队伍、列表和循环

时长:60 分钟

学习目标

  • 将多个对象存储在列表
  • 用循环遍历对象列表,并对每个对象调用方法
  • 调试常见错误:self 缺失、缺少括号 ()、变量名不一致

组建队伍(15分钟)

有了类之后,你可以创建任意多个对象,把它们存在列表里——就像存其他值一样:

team = [
    Pokemon('Pikachu',    100, 20),
    Pokemon('Charmander',  90, 18),
    Pokemon('Squirtle',    95, 15),
]

# 循环遍历队伍,打印属性
for p in team:
    print(p)          # 使用 __str__

# 找到 HP 最高的宝可梦
strongest = team[0]
for p in team:
    if p.hp > strongest.hp:
        strongest = p
print(f'最强的是: {strongest.name}')

简单战斗模拟(25分钟)

现在我们来搭建一个简单的两队对战。一步一步跟着做:

import random

team_a = [Pokemon('Pikachu', 100, 20), Pokemon('Eevee', 80, 15)]
team_b = [Pokemon('Geodude', 70, 25), Pokemon('Onix', 90, 22)]

def alive(team):
    return [p for p in team if p.hp > 0]

round_num = 1
while alive(team_a) and alive(team_b):
    print(f'--- 第 {round_num} 回合 ---')
    attacker = random.choice(alive(team_a))
    defender = random.choice(alive(team_b))
    attacker.attack(defender)
    if alive(team_b):   # team_b 反击
        attacker2 = random.choice(alive(team_b))
        defender2 = random.choice(alive(team_a))
        attacker2.attack(defender2)
    round_num += 1

if alive(team_a):
    print('A队获胜!')
else:
    print('B队获胜!')

调试诊所(15分钟)

老师有一段有 bug 的战斗代码,里面有三个错误。和搭档比赛,看谁先找到并修复所有错误。Bug 藏在:

  1. 方法定义中缺少 self
  2. 方法调用时缺少 ()
  3. 循环变量名使用不一致

出口票

  1. for p in team: p.show_stats() 做了什么?
  2. 为什么我们用 alive(team_a) 函数,而不是直接在 while 条件里检查 HP?

第五课时:设计你自己的类

时长:60 分钟

学习目标

  • 选择主题,在纸上设计类,写代码
  • 独立实现一个类,包含 __init__、4 个方法和 __str__
  • 向搭档解释你的设计

先设计——不要碰键盘!(15分钟)

编写代码(35分钟)

把你的对象卡片变成一个能运行的 Python 类。要求:

  1. __init__ 设置全部 4 个属性
  2. 4 个方法——至少 2 个必须使用 if
  3. __str__ 返回一行美观的摘要
  4. 至少一个方法必须接收一个参数(从外部传入的值)
  5. 创建 2 个对象,调用至少 3 个方法

起始代码

复制下面的骨架,把 ____ 替换成你自己的内容:

class ________:   # ← 填入你的主题名
    def __init__(self, name, _____, _____, _____):
        self.name = name
        # TODO: 设置你的其他 3 个属性

    def method_1(self):
        # TODO: 写一个简单动作
        pass

    def method_2(self):   # ← 必须用 if
        # TODO: 写一个包含 if/else 的方法
        pass

    def method_3(self, target):   # ← 接收参数
        # TODO: 写一个操作 target 的方法
        pass

    def method_4(self):   # ← 必须用 if
        # TODO: 再写一个包含 if/else 的方法
        pass

    def __str__(self):
        return f'...'   # TODO: 返回美观的一行摘要

分步指南

  1. 第 1 步:选一个主题名,把 class ________: 改成你自己的类名(如 Dragon)。
  2. 第 2 步:填写 __init__ 的参数和属性。想想你的对象需要记住哪些信息。
  3. 第 3 步:method_1——一个简单的动作,比如 roar()(咆哮)或 celebrate()(庆祝)。
  4. 第 4 步:method_2——必须包含 if。比如"如果 HP 太低,就恢复一些"。
  5. 第 5 步:method_3——接收一个 target 参数。比如攻击另一个对象。
  6. 第 6 步:method_4——也必须包含 if。比如"如果年龄够大,能力就提升"。
  7. 第 7 步:__str__,用 f-string 返回一行摘要。
  8. 第 8 步:创建 2 个对象,调用至少 3 个方法测试。
显示完整示例(Dragon 类)
class Dragon:
    def __init__(self, name, fire_power, hp, age):
        self.name       = name
        self.fire_power = fire_power
        self.hp         = hp
        self.age        = age

    def breathe_fire(self, target):
        target.hp -= self.fire_power
        if target.hp <= 0:
            print(target.name, '被击败了!')

    def rest(self):
        if self.hp < 100:
            self.hp += 20
            print(f'{self.name} 休息并恢复了 HP。')
        else:
            print(f'{self.name} 已经满 HP 了!')

    def grow_up(self):
        self.age += 1
        if self.age >= 10:
            self.fire_power += 5
            print(f'{self.name} 长大了!火焰威力提升了。')

    def roar(self):
        print(f'{self.name} 咆哮了一声!')

    def __str__(self):
        return f'{self.name} (年龄: {self.age}, HP: {self.hp}, 火焰: {self.fire_power})'

# 创建 2 个对象并测试
draco = Dragon('Draco', 30, 80, 9)
smoky = Dragon('Smoky', 25, 90, 11)

print(draco)
draco.breathe_fire(smoky)
print(smoky)
draco.rest()
draco.grow_up()

展示与讲解(10分钟)

每位同学打开 Thonny,在 Python Shell 中演示一个方法。全班提问:"这个方法做了什么?如果运行两次会怎样?"

出口票

写下一件今天觉得简单的事,和一件觉得困惑的事。

关键词汇