2017年9月27日 星期三

Python 進一步 - 類 Class 和物件 Object


若是頭一擺來遮,建議先來踏話頭

這篇是用台語文寫--ê,若是有一寡詞看無,請來遮掀字典: 臺灣閩南語常用辭典


類 (Class), 物件 (Object), 和 Oó-óo-phi (OOP)

佇開始講 Python ê class 進前,咱先介紹類(class)和物件(object) 佇程式設計歷史上 ê 意義。當然,你若是無興趣,嘛是會當躘過這段古。毋過,我是感覺了解這段你會對 class ê 使用有較清楚 ê 了解。
物件毋是 Python 孤有ê物。伊是用來支援一種設計程式 ê 經典方式: OOP (Object-Oriented Programming,台羅: óo-óo-phi)。

OOP 是超越程式語言之上 ê 一種程式設計 ê 典範 (Paradigm)。

簡單講,就是佇程式愈來愈大,若來若複雜,就有人開始思考,研究欲按怎寫才會予程式會當濟人合作,應付複雜 ê 需求,穩定閣好用咧? 經過一寡研究,就歸納出愛共程序( Procedural) 思考,轉做物件 (Object) ê思考ê 頭殼。

若毋是捌佇咧古早 ê 環境中寫程式,可能僫體會這咧改變有偌關鍵。就干焦現此時出世 ê 囡仔無法度體會無民主 ê 戒嚴時代。民主對in 來講就干焦空氣遐爾仔自然。現此時 ê 人寫程式, OOP 嘛是無所不在。 你這馬當佇學 ê Python,本底就是用 OOP ê 範去設計出來--ê。
Python ê 使用者,就是徛佇 OOP 頂仔。

Python 裡 ê 類 (Class, 嘛會當音譯: Ku-la-su),就是用來支援 OOP ê 型態。

uì Class 造出來 ê,抑是生出來 ê 實體 ê 物,就號做物件 (Object)。咱會使共 Class 想做仔,用粿共紅龜粿一塊一塊印出來,紅龜粿就是物件(Object)。正經佇 Python 內底走跳--ê 是 Object,Class 只是咱用來雕刻出 object ê 型。

聽甲霧嗄嗄? 咱就來用一个例來簡單解說。


設計動物園 - 簡單想一咧

準講咱欲來設計一咧動物園,欲按怎開始咧? 咱先看欲按怎管理動物。
這間動物園一開始tsh,獅,開始。獅有四枝跤,普通是黃色--ê。
lion_legs = 4
lion_color = 'yellow'

看來袂䆀。
閣徙落來,你想欲添另外一隻動物,雞,
chicken_legs = 4
chicken_color = 'black'

你一聲就會感覺按呢寫毋是勢,一咧動物加兩的變數,若動物愈來愈濟,你毋就變數一直添落去? 這時,你想著會當用進前學過 ê 名單:

lion = [ 4, 'meat' ]
chicken = [ 2, 'rice' ]

頭一咧欄位是跤ê數目,第二是食物。這馬,咱動物園內底有 5 隻獅, 十隻雞,攏總幾枝跤? 咱會相欲定一咧函數來算,佇算進前,愛先定一咧名單來共所有 ê  動物囥入去,咱會按呢寫:

# five lions
for i in range(1, 6):
animals.append(lion)
# ten chicken
animals.append(chicken)
for i in range(1, 10):
count_legs(animals)

 按呢看起來袂䆀,會曉用名單來共整理一咧,咱共這咧算跤 ê 程式,寫做一咧函式:

def count_legs(animals):
s = 0
for one in animals:
s = s + one[0]
print(s)

紲落來,你可能開始寫真濟無仝的函式,來算動物食偌濟,啥物色,。。。。,所有咱會閣有濟濟函式:

def count_food(animals):
def count_color(animals):
def can_fly(animal):
...
def can_swim(animal):

佇頂仔的例中方(tiőng),咱會曉用名單(lists)來共一款動物的性質抾做伙,是真好的改進。無干焦 lion_leg,lion_food,lion_color,...,咱就愛起造袂少的變數來予 Lion 用。這寡變數是互相獨立,咱是靠伊的名裡的 lion 來了解in攏是獅仔个。按呢會予人感覺散ia̍h-ia̍h,你愛會記逐个和 lion 有關係的變數。

用名單(Lists)就加真好,當然,Python 有閣較好用的資料型態,親像字典(Dictionary)。毋過咱共伊斟酌看一咧: 閣較按怎設計,都是函式和欲處理的資料是分開--ê。

設計動物園 - 物件為中心

其實, OOP 是和咱人認識世界ê方法真sîng。咱一想著一隻狗,就會聯想著伊有毛,四支跤,會走,啥物花色。咱一想著鳥仔,就會想著伊會飛,有羽毛,兩支跤。魚仔會泅水,無跤,有翅。雖然逐種動物千變萬化。毋過,in ê 特色袂差真濟,例外真少,因為咱人生來就會曉分類。Python ê Class 就是提供予咱分類 ê 工具。

欲按怎用咧,咱先內定義一咧 Animial 類:
class TheAnimal():
can_move = True
def __init__(self, name, color, legs):
self.name = name
self.legs = legs
self.color = color

 以  class 關鍵字𤆬頭,後壁硩 class 名。
Class ê 名, 佇 Python ê 慣勢,逐字合起來,每一个字ê頭一咧字母大寫。
can_move 號做 class ê 性質 (attribute)。伊是一咧變數,只不過伊是 TheAnmial 个。咱共逐个動物攏有个,仝款 ê 特色囥佇 TheAnimal ê 性質。佇遮咱認為動物和植物抑是無生物上大ê差別是: 伊會振動。這是所有動物共通--ê,你會當親像普通變數仝款使用伊:

>>> TheAnimal().can_move
>>> True

咱先用這个類來 "生", 抑是創作幾隻動物:

lion1 = TheAnimal('lion', 'brown', 4)
lion2 = TheAnimal(''lion', 'white', 4)
chicken = TheAnimal('chicken', 'yellow', 2)

佇頂仔三的運算式,就是 uì 類來起造三的物件 (object)。

動物是虛--ê (abstract),抑是講抽象ê 分類。lion1,lion2,chicken 才是真正 ê 生物,佇程式裡號做物件(object)。

物件和生物仝款,有伊的生死。生就是伊開始存在程式中(當然, 計算機科學 ê 定義閣較嚴格是占用記憶體)。死就是伊無佇這咧程式阿。生物件出來,專業名詞是 instantsiation。物件 (object) 嘛號做實體(instance)。

def __init__(self, name, color, legs)  函式是 TheAnimal() 建構式 (Constructor),也就是佇咧生一隻動物的時,一定會呼著 ê 函式。咱佇生的時,順紲共伊的 attributes 指定--落去。咱佇生物件的時落ê參數,就是欲予 __init__() 會參數。

咱佇生物件的時,指定伊的一寡性質: 佗一種動物 (lion, chicken),色緻 (brown, white, yellow),幾支跤。所以 lion2 這个變數代表 ê 就是 "一隻白色,四支跤 ê獅仔"。

物件生落來了後,才想欲知影伊的性質,嘛是親像變數仝款:

print(lion1.name) # 'lion'
print(chicken.legs) # 2

類 ê 變數和實體 ê 變數

咱有注意著無?  __init__(self,...) 第一个參數是 self。佇 class ê 所有方法 (method,也就是函式,佇咧 class 裡咱叫做 method), 一定愛是 self。伊是一咧特別 ê 參數,代表物件伊家己。lion1 伊家己就是 lion1lion2 伊家己就是 lion2。按呢毋是廢話? 咱和一開始看著 ê can_move 比較,就知影伊的奇巧佇佗位。

can_move類 ê 變數

__init__(self, ...) 內底,self.nameself.colrself.legs 攏是實體 ê 變數

類 ê 變數,是類生來就有 ê 性質。以咱的動物來講,咱定義所有動物就是會振動,這是就算咱人猶未發現 ê 物種, 毋知名--ê,攏是按呢。
實體 ê 變數,就有各種動物無仝 ê 變化,伊是這咧實體家己--ê,捌的實體無一定佮伊仝款。lion 四跤,chicken 兩跤。平平 lion,lion1 咖啡色,lion2 白色。所以

lion1.can_move # True, 合法, 實體是 TheAnimal 類
chicken.can_move # True 合法, 實體是 TheAnimal 類
TheAnimal().can_move # True,合法。can_move 是類 ê 變數
TheAnimal().legs # 無合法, legs 是實體 ê 變數

重寫動物園


定義了後,咱重寫動物園和算跤數ê程式:

class TheAnimal():
can_move = True
def __init__(self, name, color, legs):
self.name = name
self.legs = legs
self.color = color def legs(self):
legs = 0
return self.legs def count_legs(animals): for i in animals:
## The lion attributes
legs = legs + i.legs return legs animals=[] lion = TheAnimal('lion', 'yellow', 4)
animals.append(lion)
## the duck attributes chicken = TheAnimal('chicken', 'white', 2) # five lions for i in range(1, 6): # ten chicken
print(count_legs(animals))
for i in range(1, 10): animals.append(chicken)

你會感覺這種寫法,加真媠氣。雖然無一定較少 coding。這種方式是較費時間佇一開始 ê 定義。等到後壁,你會感覺 code 真清氣,真清楚。因為伊共和物件有關係 ê 性質,攏抾做伙佇物件--裡,你免煩惱落--去。

閣進一步,連一寡函式,嘛會使整入去 class 內底,只要伊是這咧 class 特別有,抑是實體特有--ê,我就無閣寫實例,干焦寫一咧殼來意思意思,你會當家己思考欲按怎共肉添入去


class TheAnimal():
can_move = True
def __init__(self, name, color, legs):
self.name = name
self.legs = legs
self.color = color
def can_fly(self, ...):
def can_run(self, ...): ... ...
def run(self, ...):
def can_swim(self, ...): ZZZZ ... def fly(self, ...:
some_animal.fly()
... def swim(self, ..): if some_animal.can_fly():
some_animal.run()
if some_animal.can_run():

咱的感覺,變數是性質,函式是動作,是行為。逐種動物有伊特別 ê 運動方式。佇 Procedural 方式,行為佮性質是分開。佇 OOP 裡,連行為攏整做伙。

當然,佇遮咱會介紹真粗淺,毋過有夠有咱了解 OOB ê 基本概念和 Python class ê 用法。

沒有留言:

佇 Linux 來看GPX 檔案

最近定定有戶外活動。使用𤆬路機 (GPS) 來記錄行過的路線。普通我記錄路線,攏是用手機仔抑是專門个𤆬路機,罕得用電腦來看。 毋過,"仙人拍鼓有時錯,跤步踏差啥人無"。有一擺我無細膩,袂記得共一擺活動的路線收煞起來,閣直接開始記錄下一擺的活動,按呢共幾落...