Python 自學第十二天:Class 類別的應用範例

實際練習幾個類別的運用,將程式碼封裝在裡面,使用者不需要寫很多行程式碼,即可操作。

範例一:檔案讀取

定義一個檔案讀取的 Class,將如何讀取檔案的將程式碼封裝在裡面。

1
2
3
4
5
6
7
8
class ReadFile:
# 定義「創造實體的初始化函式」
def __init__(self, path):
self.name = path
self.fileObj = open(self.name, mode="r")

def readFile(self):
return self.fileObj.read()

如下列程式碼使用時:

  • line 1 首先先創造 ReadFile類別 的實體 ff 實體有兩個變數:路徑名稱 name 和以該路徑開啟的檔案物件 fileObj
  • line 2 以 f 呼叫 readFile() 函式時,會讓檔案物件 fileObj 呼叫 read() 並且回傳讀取到的資料。最後成功輸出結果!
1
2
3
4
5
6
7
8
9
f = ReadFile("file1.txt")
txt = f.readFile()
print(txt)

# 輸出結果:
# 測試 Python 第一行
# 這是第二行,接在第二行後面
# 我是 Jenifer
# 想要第三行,新增的字串!

範例二:英雄與怪物 (一)

定義一個怪物和一個英雄的 Class,情境如下:

  • 英雄可以選擇攻擊目標。
  • 英雄可以攻擊怪物,怪物不能攻擊英雄。
  • 英雄不需要血條,怪物需要血條。
  • 英雄的攻擊力介於 基礎攻擊力*0.8 ~ 基礎攻擊力*1.2 的範圍。
  • 英雄會一直攻擊怪物,直到怪物死亡。
  • 顯示出怪物剩餘血量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import random

class Monster:
def __init__(self, m_name, m_HP=500):
self.name = m_name
self.HP = m_HP


class Hero:
def __init__(self, h_name, h_attack=50):
self.name = h_name
self.attack = h_attack
self.enemy = None # 英雄的敵人還未知

def Target(self, m):
self.enemy = m # 英雄選擇的攻擊目標,是一個怪物物件

def Attack(self):
self.enemy.HP = self.enemy.HP - self.attack*random.uniform(0.8, 1.2)
if self.enemy.HP < 0:
self.enemy.HP = 0
else:
print(f"剩下 {round(self.enemy.HP, 3)} 血量")

使用時,如下列程式碼:

  • line 1 首先先創造 Monster類別 的實體 monstermonster 實體有兩個變數:名字 name血量 HP (預設 500)。
  • line 2 創造 Hero類別 的實體 herohero 實體有三個變數:名字 name攻擊力 attack敵人 enemy (等等會儲存一個怪物物件)。
  • line 3 英雄選擇攻擊目標時,將怪物物件儲存到 enemy 變數中。怪物物件有自己的名字血量
  • line 5 英雄攻擊時,敵人的血量減去英雄攻擊力 0.8~1.2 倍的範圍。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
monster = Monster("卡比獸")
hero = Hero("Jenifer")
hero.Target(monster)
while monster.HP > 0:
hero.Attack()
else:
print(hero.name + " 擊敗了" + monster.name)


# 剩下 453.401 血量
# 剩下 408.594 血量
# 剩下 356.474 血量
# 剩下 310.718 血量
# 剩下 265.959 血量
# 剩下 217.678 血量
# 剩下 169.36 血量
# 剩下 114.043 血量
# 剩下 65.406 血量
# 剩下 6.47 血量
# Jenifer 擊敗了卡比獸

範例三:英雄與怪物 (二)

定義一個角色的 Class,情境如下:

  • 角色有名字、血量和攻擊力基本屬性。
  • 角色可以確認攻擊目標。
  • 角色攻擊完敵人後,顯示敵人剩餘血量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import random

class Character:
def __init__(self, c_name, c_HP=600, c_attack=50):
self.name = c_name
self.HP = c_HP
self.attack = c_attack
self.enemy = None

def Target(self, m):
self.enemy = m

def Attack(self):
self.enemy.HP = self.enemy.HP - self.attack*random.uniform(0.8, 1.2)
if self.enemy.HP < 0:
self.enemy.HP = 0
print(f"{self.enemy.name} 剩下 {round(self.enemy.HP, 3)} 血量")
else:
print(f"{self.enemy.name} 剩下 {round(self.enemy.HP, 3)} 血量")

另外包裝一個 battle() 函式,將英雄攻擊怪物的流程包裝在內,情境如下:

  • 英雄先將怪物視為攻擊目標,然後攻擊怪物。
  • 怪物被攻擊後,將英雄視為攻擊目標。
  • 英雄會攻擊兩次,怪物只攻擊一次。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def battle(hero, mon):
print(hero.name + "率先發動攻擊~")
hero.Target(mon)
hero.Attack()
mon.Target(hero)
while hero.HP > 0 and mon.HP > 0:
hero.Attack()
if mon.HP > 0:
print(mon.name + "反攻!")
mon.Attack()
if hero.HP > 0:
print("-------------------- new round --------------------")
print(hero.name + " 攻擊" + mon.name + "~~~")
hero.Attack()
else:
if hero.HP == 0:
print(mon.name + " 擊敗了" + hero.name)
elif mon.HP == 0:
print(hero.name + " 擊敗了" + mon.name)

使用時,利用 Character類別 創造一個怪物實體、一個英雄實體。將怪物和英雄實體傳入 battle() 函式。

1
2
3
monster = Character("卡比獸", 500, 280)
my_hero = Character("Jenifer", 600, 100)
battle(my_hero, monster)

英雄勝利劇本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Jenifer率先發動攻擊~
# 卡比獸 剩下 409.446 血量
# 卡比獸 剩下 303.631 血量
# 卡比獸反攻!
# Jenifer 剩下 338.239 血量
# -------------------- new round --------------------
# Jenifer 攻擊卡比獸~~~
# 卡比獸 剩下 216.06 血量
# 卡比獸 剩下 110.494 血量
# 卡比獸反攻!
# Jenifer 剩下 93.172 血量
# -------------------- new round --------------------
# Jenifer 攻擊卡比獸~~~
# 卡比獸 剩下 3.573 血量
# 卡比獸 剩下 0 血量
# Jenifer 擊敗了卡比獸

英雄失敗劇本:

1
2
3
4
5
6
7
8
9
10
11
12
# Jenifer率先發動攻擊~
# 卡比獸 剩下 382.197 血量
# 卡比獸 剩下 284.08 血量
# 卡比獸反攻!
# Jenifer 剩下 281.792 血量
# -------------------- new round --------------------
# Jenifer 攻擊卡比獸~~~
# 卡比獸 剩下 189.142 血量
# 卡比獸 剩下 70.712 血量
# 卡比獸反攻!
# Jenifer 剩下 0 血量
# 卡比獸 擊敗了Jenifer

參考資料:
彭彭的課程:Python 實體物件的建立與使用 - 下篇 - 實體屬性 Instance Attributes