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

第一年 · 第13周

第十三章:会做事的方法

上周你用 __init__ 和 self 创建了对象。本周你的对象要升级了:它们将能做事。你将编写方法让宝可梦攻击、治疗和显示属性。你还会学习 __str__,让 print() 显示有用的信息而不是丑陋的内存地址。

第三课时:会做事的方法

时长:60 分钟

学习目标

  • 编写读取和修改属性的实例方法
  • 在方法内使用 if 语句
  • 添加 __str__print() 显示美观的描述

热身:Bug 猎人(10分钟)

在碰键盘之前,找出下面代码中的三个错误:

class Dog:
    def __init__(name, breed):   # Bug 1
        self.name  = name
        self.breed = breed

    def bark(self):
        print(self.name, 'says: Woof!')

rex = Dog('Rex', 'Labrador')
rex.bark                         # Bug 2
print(rex.colour)                # Bug 3
显示答案

Bug 1:__init__ 的第一个参数必须是 self。应该是 def __init__(self, name, breed):

Bug 2:调用方法需要加括号。应该是 rex.bark()

Bug 3:colour 属性从未被定义。应该是 rex.breed,或者需要在 __init__ 中添加 self.colour

添加方法(30分钟)

方法是住在类里面的函数。它们总是把 self 作为第一个参数,这样才能访问对象的属性。

class Pokemon:
    def __init__(self, name, hp, damage):
        self.name   = name
        self.hp     = hp
        self.damage = damage

    # 攻击另一只宝可梦
    def attack(self, target):
        target.hp -= self.damage
        print(f'{self.name} attacks {target.name} for {self.damage} damage!')
        if target.hp <= 0:
            print(f'{target.name} fainted!')

    # 治疗到最多 100 HP
    def heal(self, amount):
        if self.hp + amount > 100:
            self.hp = 100
        else:
            self.hp += amount
        print(f'{self.name} healed! HP is now {self.hp}.')

    # 显示当前属性
    def show_stats(self):
        print(f'{self.name} — HP: {self.hp} | Damage: {self.damage}')

试一试:

pikachu    = Pokemon('Pikachu',    100, 20)
charmander = Pokemon('Charmander',  90, 18)

pikachu.show_stats()
pikachu.attack(charmander)
charmander.show_stats()
charmander.heal(30)
charmander.show_stats()

让 print() 变美观 — __str__(10分钟)

现在如果直接 print(pikachu),会显示类似 <__main__.Pokemon object at 0x7f…> 这样丑陋的东西。我们可以修复它:

    # 在 Pokemon 类中添加这个方法
    def __str__(self):
        return f'{self.name} (HP: {self.hp})'

# 现在这样就能正常显示了:
print(pikachu)    # Pikachu (HP: 100)

配对练习(10分钟)

和你的搭档一起,给 Pokemon 类添加一个新方法。从下面选一个:

  • level_up
  • use_potion
  • evolve
  • flee

要求:你的方法必须包含一个 if 语句。

显示示例答案
def level_up(self):
    self.damage += 5
    if self.hp < 100:
        self.hp = 100
    print(f'{self.name} leveled up! Damage: {self.damage}, HP: {self.hp}')

def flee(self):
    if self.hp > 20:
        print(f"{self.name} doesn't need to flee!")
    else:
        print(f"{self.name} ran away safely!")

关键点:每个方法都有 self 作为第一个参数,并且都包含至少一个 if 语句来做条件判断。

出口票

  1. self 在方法内部指的是什么?
  2. 用一句通俗的话解释 __str__ 做了什么。

关键词汇