類別
截至目前為止,我們使用 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
的錯誤訊息。