類別
截至目前為止,我們使用 type() 函數觀察的資料或是容器,都是 Python 的內建類別,像是 str、int 或 list 等,不同的這些類別可能包含不同的屬性(attributes)與方法(methods),像是一個文字有 upper() 與 lower() 方法能夠改變大小寫:
my_name = "Tony"
print my_name.upper()
print my_name.lower()

屬性與方法聽起來有點抽象,但實際上它們就是隸屬於某個類別的資料(data)與函數(function)。
7.1 自訂類別
7.1.1 屬性
除了使用內建的類別以外,Python 也容許我們自訂類別藉此建立擁有客製方法與屬性的物件。我們使用 class 語法來定義類別,並使用大寫開頭(Capitalized)單字為類別命名。現在讓我們來建立一個類別叫做 Building,建築物有一個屬性是名稱,就像在玩戰略遊戲一般,可以蓋城鎮中心、軍營或者修道院。
class Building():
def __init__(self, name):
self.name = name
town_center = Building("Town Center")
barrack = Building("Barrack")
monastery = Building("Monastery")
print town_center.name
print barrack.name
print monastery.name

如果對於 __init__ 方法與 self 參數感到困惑,就先記得這是 Python 的慣例,它用來幫助我們創造屬於這個類別的物件。
7.1.2 方法
建築物除了具有名稱這個屬性,還有一個基本方法是生產,比如城鎮中心能夠生產村民、軍營能夠生產戰士或者修道院能夠生產僧侶。
class Building():
def __init__(self, name, unit):
self.name = name
self.unit = unit
def create(self):
return "%s 生產 %s" %(self.name, self.unit)
town_center = Building("Town Center", "Villager")
barrack = Building("Barrack", "Swordsman")
monastery = Building("Monastery", "Monk")
print town_center.create()
print barrack.create()
print monastery.create()

7.2 繼承
戰略遊戲中的建築除了具備前述的基本屬性及方法,有時還會有其他進階的功能,比如具備庇護或者攻擊的能力。因此我們會需要自訂新的類別來滿足這些建築,但假如每次自訂新的類別就必須複製貼上建築的基本屬性及方法,不但很辛苦,未來也不容易維護,為了解決這樣的難題,類別具有繼承的特性,例如 Castle 類別可以繼承 Building。
class Building():
def __init__(self, name, unit):
self.name = name
self.unit = unit
def create(self):
return "%s 生產 %s" %(self.name, self.unit)
class Castle(Building):
pass
castle = Castle("Castle", "Unique Unit")
print castle.name
print castle.create()

因為在自訂 Castle 類別時繼承了 Building 類別(在小括號中輸入想要繼承的類別名稱),即便我們只有在 Castle 類別中輸入 pass,這個類別還是具備名稱屬性與生產方法。
7.2.1 新增或改寫方法
繼承了 Building 類別的 Castle 類別可以新增與改寫方法:
class Building():
def __init__(self, name, unit):
self.name = name
self.unit = unit
def create(self):
return "%s 生產 %s" %(self.name, self.unit)
class Castle(Building):
def create(self):
return "%s 生產 %s 與 Trebuchet" %(self.name, self.unit)
def attack(self):
return "%s fires arrows!" %(self.name)
castle = Castle("Castle", "Unique Unit")
print castle.name
print castle.create()
print castle.attack()

7.2.2 新增屬性
在繼承時使用 super() 就可以建立新的屬性並保留原類別的屬性,例如我們可以在繼承 Building 的 Castle 類別中新增一個 siege_unit 屬性:
class Building(object):
def __init__(self, name, unit):
self.name = name
self.unit = unit
def create(self):
return "%s 生產 %s" %(self.name, self.unit)
class Castle(Building):
def __init__(self, name, unit, siege_unit):
super(Castle, self).__init__(name, unit)
self.siege_unit = siege_unit
def create(self):
return "%s 生產 %s 與 %s" %(self.name, self.unit, self.siege_unit)
castle = Castle("Castle", "Unique Unit", "Trebuchet")
print castle.create()

這裡的程式要特別注意我們讓 Building 類別先繼承 Python 的 object 類別,如此才能夠順利使用 super(),否則我們的 Building 會被歸類為舊式類別(old style class),在使用 super() 時會出現 TypeError: super() argument 1 must be type, not classobj 的錯誤訊息。
