Python類別與例外- 高中資訊科技概論教師黃建庭的教學網站

文章推薦指數: 80 %
投票人數:10人

(A) 類別. 類別像是一個蛋糕的模子,這個蛋糕的模子可以重複製作出相同的蛋糕,就像類別可以宣告出相同的物件,可以讓程式不斷地被重複利用。

在Python使用class宣告 ... 高中資訊科技概論教師黃建庭的教學網站搜尋這個協作平台 黃建庭的教學網站新版黃建庭教學網站高三資訊課程108資訊科技基礎C++與PythonPython程式設計Python與資料分析C++演算法解題(1)C++演算法解題(2)機器學習教學平台ZSOJ資訊能力競賽考古題資訊能力檢定APCSRaspberry樹莓派ArduinoArduino與Scratch2FreeBSD/Linux筆記網管筆記AppInventor2Scratch2PHP程式設計JavaScript程式設計107資訊科技概論程式設計--使用機器人micro:bitAmeba3D列印JetBotDjangoLXR軟體使用心得相簿學生榮譽榜學經歷與著作與我聯絡連結高中生程式解題系統(zerojudge)UvaOnlineJudge資訊之芽(fb)Bebras系統管理新聞協作平台地圖最新協作平台活動 FreeHitCounter 版權宣告學校上課使用,可不標記作者 黃建庭的教學網站‎>‎Python程式設計‎>‎ Python類別與例外 (A) 類別 類別像是一個蛋糕的模子,這個蛋糕的模子可以重複製作出相同的蛋糕,就像類別可以宣告出相同的物件,可以讓程式不斷地被重複利用。

在Python使用class宣告類別,就可以重複宣告此類別的物件,以下進行類別的實作。

(A-1)實作類別 Python中類別就是使用class定義類別內的資料與操作的函式,函式「__init__」表示宣告類別時會自動執行的函式,第一個參數為self,表示自己,第二個參數為輸入類別的資料,可以在宣告屬於該類別的物件時,同時傳入資料到該物件,傳入的資料可以指定給「self.變數名稱」,表示該物件有了儲存資料的變數,例如以下程式範例。

行號 範例 執行結果 12345 classAnimal():    def__init__(self,name):        self.name=namea=Animal('動物')print(a.name) 動物 解說 第1到3行:定義類別Animal,宣告函式「__init__」,函式「__init__」輸入參數為self與name,將name指定給物件變數self.name。

第4行:宣告一個類別Animal的物件,輸入「動物」到類別Animal的初始化函式「__init__」,將此物件貼上物件a的標籤。

第5行:顯示物件a的變數name到螢幕上。

  (A-2)繼承 可以繼承原有的類別,修改延伸出新的類別,原有的類別被稱為基礎類別(baseclass)或雙親類別(parent class),新的類別被稱為衍生類別(derived class)或子類別(childclass),這個衍生類別就自動擁有基礎類別的變數與函式。

使用「class衍生類別(基礎類別)」來定義類別間的繼承關係,衍生類別就繼承了基礎類別;在衍生類別中使用「super().基礎類別的函式」可以呼叫基礎類別的函式來幫忙,若衍生類別所需要的功能已經在基礎類別定義過了,就可以呼叫基礎類別幫忙,重複利用已經撰寫過的程式碼。

當所有衍生類別都需要更改,而且所需功能都相同時,若該功能可以更改基礎類別達成,就直接修改基礎類別,就會影響所有的衍生類別。

利用衍生類別與基礎類別的關係達成程式碼的重複利用,減少程式的錯誤,發揮物件導向程式設計的優點。

以下為類別的繼承範例。

行號 範例 執行結果 12345678910 classAnimal():     def__init__(self,name):       self.name=nameclassDog(Animal):     def__init__(self,name):       super().__init__('小狗'+name)a=Animal('動物')d=Dog('小白')print(a.name)print(d.name) 動物 小狗小白   解說 第1到3行:定義類別Animal,宣告函式「__init__」,函式「__init__」輸入參數為self與name,將name儲存到物件變數self.name。

第4到6行:定義類別Dog繼承自類別Animal,宣告函式「__init__」,函式「__init__」輸入參數為self與name,使用「super()」呼叫基礎類別Animal的函式「__init__」,傳入「小狗」串接name的字串。

第7行:宣告一個類別Animal的物件,輸入「動物」到類別Animal的初始化函式「__init__」,將此物件貼上物件a的標籤。

第8行:宣告一個類別Dog的物件,輸入「小白」到類別Dog的初始化函式「__init__」,將此物件貼上物件d的標籤。

第9行:顯示物件a的變數name到螢幕上。

第10行:顯示物件d的變數name到螢幕上。

  (A-3) 覆寫函式 衍生類別可以繼承基礎類別的資料與函式,在衍生類別內重新改寫基礎類別的函式,讓衍生類別與基礎類別的相同函式有不同功能,這樣的改寫函式稱作「覆寫」。

以下類別Dog繼承了類別Animal,兩個類別都有函式sound,類別Animal的函式sound不執行任何動作,而類別Dog繼承類別Animal,所以有了函式sound,但在類別Dog中重新覆寫函式sound,讓類別Dog的函式sound會印出「汪汪叫」在螢幕上。

行號 範例 執行結果 12345678910111213 classAnimal():     def__init__(self,name):          self.name=name     defsound(self):           passclassDog(Animal):       def__init__(self,name):             super().__init__('小狗'+name)        defsound(self):          return'汪汪叫'd=Dog('小黑')print(d.name)print(d.sound()) 小狗小黑 汪汪叫   解說 第1到5行:定義類別Animal,定義函式「__init__」,函式「__init__」輸入參數為self與name,將name儲存到物件變數self.name(第2到3行)。

定義函式sound,使用pass表示沒有執行任何程式(第4到5行)。

第6到10行:定義類別Dog繼承自類別Animal,定義函式「__init__」,函式「__init__」輸入參數為self與name,使用「super()」呼叫基礎類別Animal的函式「__init__」,傳入「小狗」串接name的字串(第7到8行)。

定義函式sound,回傳「汪汪叫」(第9到10行)。

第11行:宣告一個類別Dog的物件,輸入「小黑」到類別Dog的初始化函式「__init__」,將此物件貼上物件d的標籤。

第12行:顯示物件d的變數name到螢幕上。

第13行:顯示物件d的函式sound的執行結果到螢幕上。

  8-1-4.新增參數的覆寫函式 衍生類別可以繼承基礎類別的資料與函式,在衍生類別內重新改寫基礎類別的函式,讓衍生類別與基礎類別的相同函式有不同功能,這樣的改寫函式稱作「覆寫」,在覆寫函式時,可以新增參數。

以下類別Dog繼承了類別Animal,兩個類別都有函式「__init__」,類別Dog繼承類別Animal,所以有了函式「__init__」,但在類別Dog中重新覆寫函式「__init__」時,多出了參數leg,使用self.leg儲存參數leg。

行號 範例(ch8\8-1-4-新增參數的覆寫函式.py) 執行結果 1234567891011121314 classAnimal():     def__init__(self,name):           self.name=name     defsound(self):          passclassDog(Animal):      def__init__(self,name,leg):          super().__init__('小狗'+name)          self.leg=leg     defsound(self):          return'汪汪叫'd=Dog('小黑',4)print(d.name,'有',d.leg,'條腿')print(d.name,d.sound()) 小狗小黑有 4條腿 小狗小黑汪汪叫   解說 第1到5行:定義類別Animal,定義函式「__init__」,函式「__init__」輸入參數為self與name,將name儲存到物件變數self.name(第2到3行)。

定義函式sound,使用pass表示沒有執行任何程式(第4到5行)。

第6到11行:定義類別Dog繼承自類別Animal,定義函式「__init__」,函式「__init__」輸入參數為self、name與leg,使用「super()」呼叫基礎類別Animal的函式「__init__」,傳入「小狗」串接name的字串,設定self.leg為leg(第7到9行)。

定義函式sound,回傳「汪汪叫」(第10到11行)。

第12行:宣告一個類別Dog的物件,輸入「小黑」與「4」到類別Dog的初始化函式「__init__」,將此物件貼上物件d的標籤。

第13行:使用函式print顯示物件d的變數name,串接「有」,串接物件d的變數leg,串接「條腿」到螢幕上。

第14行:使用函式print顯示物件d的變數name,串接物件d的函式sound的執行結果到螢幕上。

  (A-5) 新增函式 衍生類別可以繼承基礎類別的資料與函式,在衍生類別內新增基礎類別沒有的函式。

以下類別Dog繼承了類別Animal,兩個類別都有函式「__init__」與函式sound,在衍生類別Dog新增函式move,而基礎類別Animal沒有函式move。

行號 範例 執行結果   123456789101112131415 classAnimal():     def__init__(self,name):          self.name=name     defsound(self):          passclassDog(Animal):     def__init__(self,name):          super().__init__('小狗'+name)     defsound(self):          return'汪汪叫'     defmove(self):          print(self.name+'在馬路上行走')d=Dog('小黑')print(d.name,d.sound())d.move() 小狗小黑汪汪叫 小狗小黑在馬路上行走   解說 第1到5行:定義類別Animal,定義函式「__init__」,函式「__init__」輸入參數為self與name,將name儲存到物件變數self.name(第2到3行),定義函式sound,使用pass表示沒有執行任何程式(第4到5行)。

第6到12行:定義類別Dog繼承自類別Animal,定義函式「__init__」,函式「__init__」輸入參數為self與name,使用「super()」呼叫基礎類別Animal的函式「__init__」,傳入「小狗」串接name的字串(第7到8行),定義函式sound,回傳「汪汪叫」(第9到10行),定義函式move,印出self.name串接字串「在馬路上行走」(第11到12行)。

第13行:宣告一個類別Dog的物件,輸入「小黑」到類別Dog的初始化函式「__init__」,將此物件貼上物件d的標籤。

第14行:將物件d的name與呼叫物件d函式sound的回傳結果顯示在螢幕上。

第15行:呼叫物件d函式move。

  (A-6) 多型(polymorphism) 多個類別可以定義相同的函式名稱,而相同函式名稱在不同類別可以定義各自特有的功能,經由呼叫物件的函式名稱,傳入不同的物件都定義此相同函式名稱而產生不同的功能,稱作「多型」,在Python裡這些類別不一定要有繼承關係。

以下範例,類別Dog繼承了類別Animal,兩個類別都有函式who與函式sound,類別Bird沒有繼承類別Animal,但有定義相同名稱的函式who與函式sound,所以類別Animal、類別Dog與類別Bird就可以實作多型的概念,定義一個函式talk可以輸入物件,顯示輸入物件的函式who與函式sound的回傳結果,經由輸入不同的物件觀察顯示在螢幕上的字串,可以了解多型的概念。

行號 範例 執行結果 123456789101112131415161718192021222324252627 classAnimal():     def__init__(self,name):          self.name=name     defwho(self):          returnself.name     defsound(self):          passclassDog(Animal):     def__init__(self,name):          super().__init__('小狗'+name)     defsound(self):          return'汪汪叫'classBird():     def__init__(self,name):          self.name='小鳥'+name     defwho(self):          returnself.name     defsound(self):          return'啾啾叫' deftalk(obj):     print(obj.who(),'正在',obj.sound())a=Animal('動物')talk(a)d=Dog('小黑')talk(d)b=Bird('小黃')talk(b) 動物正在 None 小狗小黑正在汪汪叫 小鳥小黃正在啾啾叫   解說 第1到7行:定義類別Animal,定義函式「__init__」,函式「__init__」輸入參數為self與name,將name儲存到物件變數self.name(第2到3行),定義函式who,回傳self.name(第4到5行),定義函式sound,使用pass表示沒有執行任何事(第6到7行)。

第8到12行:定義類別Dog繼承自類別Animal,定義函式「__init__」,函式「__init__」輸入參數為self與name,使用「super()」呼叫基礎類別Animal的函式「__init__」,傳入「小狗」串接name的字串(第9到10行),定義函式sound,回傳「汪汪叫」(第11到12行)。

第13到19行:定義類別Bird,定義函式「__init__」,函式「__init__」輸入參數為self與name,設定self.name為「小鳥」串接name的字串(第14到15行),定義函式who,回傳self.name(第16到17行),定義函式sound,回傳「啾啾叫」(第18到19行)。

第20到21行:定義函式talk,輸入參數obj,印出物件obj的函式who的回傳結果,串接字串「正在」,串接物件obj的函式sound的回傳結果。

第22行:宣告一個類別Animal的物件,輸入「動物」到類別Animal的初始化函式「__init__」,將此物件貼上物件a的標籤。

第23行:呼叫函式talk,以物件a為輸入參數。

第24行:宣告一個類別Dog的物件,輸入「小黑」到類別Dog的初始化函式「__init__」,將此物件貼上物件d的標籤。

第25行:呼叫函式talk,以物件d為輸入參數。

第26行:宣告一個類別Bird的物件,輸入「小黃」到類別Bird的初始化函式「__init__」,將此物件貼上物件b的標籤。

第27行:呼叫函式talk,以物件b為輸入參數。

  (A-7) 類別內無法直接存取的變數 在類別內的變數,若在變數名稱前加上「__」,該變數無法直接使用「類別物件.__變數名稱」進行存取,達到資料保護的目的,需要在類別內定義函式,回傳「self.__變數名稱」才能存取到該變數。

行號 範例 執行結果 12345678910111213141516 classAnimal():     def__init__(self,name):          self.__name=name     defsound(self):          pass     defshow_name(self):          returnself.__name;classDog(Animal):     def__init__(self,name,leg):          super().__init__('小狗'+name)          self.leg=leg     defsound(self):          return'汪汪叫'd=Dog('小黑',4)#print(d.__name,'有',d.leg,'條腿')print(d.show_name(),'有',d.leg,'條腿') 小狗小黑有 4條腿   解說 第1到7行:定義類別Animal,定義函式「__init__」,函式「__init__」輸入參數為self與name,將name儲存到物件變數self.__name(第2到3行),定義函式sound,使用pass表示沒有執行任何程式(第4到5行),定義函式show_name回傳self.__name(第6到7行)。

第8到13行:定義類別Dog繼承自類別Animal,定義函式「__init__」,函式「__init__」輸入參數為self、name與leg,使用「super()」呼叫基礎類別Animal的函式「__init__」,傳入「小狗」串接name的字串,設定self.leg為leg(第9到11行)。

定義函式sound,回傳「汪汪叫」(第12到13行)。

第14行:宣告一個類別Dog的物件,輸入「小黑」與「4」到類別Dog的初始化函式「__init__」,將此物件貼上物件d的標籤。

第15行:若將此行的井字號(#)去除,則會出現AttributeError錯誤,因為無法直接讀取「d.__name」。

第16行:使用函式print顯示物件d的函式show_name的執行結果,串接「有」,串接物件d的變數leg,串接「條腿」到螢幕上。

  (A-8) 特殊函式(specialmethod) 存在於類別內的特殊函式,Python會讓運算子或內建函式可以與特殊函式自動對應,例如判斷兩物件是否相等的運算子「==」會自動與類別內特殊函式「__eq__」,所以在類別內重新定義特殊函式「__eq__」,類別中使用運算子「==」的運算就會直接使用特殊函式「__eq__」進行是否相等的判斷,以下程式範例就重新改寫特殊函式「__eq__」,判斷兩個物件內的變數name是否相同,決定兩物件是否相等。

行號 範例 執行結果 123456789101112131415161718192021222324 classAnimal():     def__init__(self,name):          self.__name=name     defsound(self):          pass     defshow_name(self):          returnself.__name     defeq(self,other):          returnself.__name==other.show_name()     def__eq__(self,other):          returnself.__name==other.show_name()classDog(Animal):     def__init__(self,name,leg):          super().__init__('小狗'+name)           self.leg=leg     defsound(self):          return'汪汪叫'd1=Dog('小黑',4)d2=Dog('小黑',4)print(d1.eq(d2))print(d1==d2)d3=Dog('小白',4)print(d1.eq(d3))print(d1==d3) True True False False   解說 第1到11行:定義類別Animal,定義函式「__init__」,函式「__init__」輸入參數為self與name,將name儲存到物件變數self.name(第2到3行),定義函式sound,使用pass表示沒有執行任何程式(第4到5行),定義函式show_name回傳self.__name(第6到7行),定義函式eq,輸入參數self與other,回傳self.__name是否等於物件other的函式show_name回傳的字串(第8到9行)。

定義函式「__eq__」,輸入參數self與other,回傳self.__name是否等於物件other的函式show_name回傳的字串(第10到11行)。

第12到17行:定義類別Dog繼承自類別Animal,定義函式「__init__」,函式「__init__」輸入參數為self、name與leg,使用「super()」呼叫基礎類別Animal的函式「__init__」,傳入「小狗」串接name的字串,設定self.leg為leg(第13到15行)。

定義函式sound,回傳「汪汪叫」(第16到17行)。

第18行:宣告一個類別Dog的物件,輸入「小黑」與「4」到類別Dog的初始化函式「__init__」,將此物件貼上物件d1的標籤。

第19行:宣告一個類別Dog的物件,輸入「小黑」與「4」到類別Dog的初始化函式「__init__」,將此物件貼上物件d2的標籤。

第20行:使用函式print顯示物件d1的函式eq以物件d2為輸入的運算結果。

第21行:使用運算子「==」,判斷物件d1與物件d2是否相等,會自動呼叫函式「__eq__」進行判斷,使用函式print顯示結果到螢幕上。

第22行:宣告一個類別Dog的物件,輸入「小白」與「4」到類別Dog的初始化函式「__init__」,將此物件貼上物件d3的標籤。

第23行:使用函式print顯示物件d1的函式eq以物件d3為輸入的運算結果。

第24行:使用運算子「==」,判斷物件d1與物件d3是否相等,會自動呼叫函式「__eq__」進行判斷,使用函式print顯示結果到螢幕上。

  特殊函式與運算子的對應,如下表。

  特殊函式 對應的運算子 比較運算 __eq__(self, other) self==other __ne__(self, other) self!=other __gt__(self, other) self>other __ge__(self, other) self>=other __lt__(self, other) self> other __and__(self, other) self&other __or__(self, other) self|other __xor__(self, other) self^other     特殊函式 對應的函式 內建函式 __len__(self) len(self) __str__(self) str(self) __repr__(self) repr(self)   (A-9) 組合(composition) 類別與類別之間不全然都是繼承關係,也有可能是類別A是類別B的一部分,腳是動物的一部分,但腳不是動物,腳無法繼承動物,這時就可以使用組合,在動物類別初始化時,將腳當成參數傳入,讓腳成為動物的一部分。

行號 範例 執行結果 123456789101112131415 classLeg():     def__init__(self,num,look):          self.num=num          self.look=lookclassAnimal():    def__init__(self,name,leg):          self.__name=name          self.leg=leg     defshow_name(self):          returnself.__name     defshow(self):          print(self.show_name(),'有',self.leg.num,'隻',self.leg.look,'腿')leg=Leg(4,'短短的')a=Animal('小狗',leg)a.show() 小狗有 4隻短短的腿   解說 第1到4行:定義類別Leg,定義函式「__init__」,函式「__init__」輸入參數為self、num與look,將num儲存到物件變數self.num,將look儲存到物件變數self.look。

第5到12行:定義類別Animal,定義函式「__init__」,函式「__init__」輸入參數為self、name與leg,將name儲存到物件變數self.__name,將leg儲存到物件變數self.leg(第6到8行),定義函式show_name回傳self.__name(第9到10行),定義函式show,顯示函式self.show_name的結果,串接「有」,串接self.leg.num,串接「隻」,串接self.leg.look,串接「腿」(第11到12行)。

第13行:宣告一個類別Leg的物件,輸入「4」與「短短的」到類別Leg的初始化函式「__init__」,將此物件貼上物件leg的標籤。

第14行:宣告一個類別Animal的物件,輸入「小狗」與leg到類別Animal的初始化函式「__init__」,將此物件貼上物件a的標籤。

第15行:在螢幕上顯示物件a的函式show的結果。

 (A-10)   類別方法目前所介紹的類別內方法,都屬於實例方法(instancemethod),此方法的第一個參數都是self。

類別方法(class method)作用對象為類別,會影響整個類別,也會影響類別所產生的物件,類別方法的第一個參數通常取名為cls,需在類別中函式的前一行使用裝飾器「@classmethod」,這樣的函式稱作「類別方法」。

行號 範例 執行結果 1234567891011121314151617 classAnimal():     count=0     def__init__(self):          Animal.count+=1     defkill(self):          Animal.count-=1     @classmethod     defshow_count(cls):          print('現在有',cls.count,'隻動物')a=Animal()Animal.show_count()b=Animal()Animal.show_count()c=Animal()Animal.show_count()a.kill()Animal.show_count() 現在有1隻動物 現在有2隻動物 現在有3隻動物 現在有2隻動物   解說第1到9行:定義類別Animal,初始化類別變數count為0,變數count在函式外部且前方沒有加上self,變數count是類別變數,以此類別宣告的所有物件共用一個類別變數,類別變數count使用「Animal.count」或「cls.count」進行存取。

定義函式「__init__」,函式「__init__」輸入參數為self,將類別Animal的變數count遞增1(第3到4行),定義函式「kill」,輸入參數為self,將類別Animal的變數count遞減1(第5到6行),定義show_count為類別函式,顯示字串「現在有」,串接cls.count,串接「隻動物」在螢幕上(第7到9行)。

第10行:宣告一個類別Animal的物件,將此物件貼上物件a的標籤。

第11行:呼叫類別Animal的函式show_count。

第12行:宣告一個類別Animal的物件,將此物件貼上物件b的標籤。

第13行:呼叫類別Animal的函式show_count。

第14行:宣告一個類別Animal的物件,將此物件貼上物件c的標籤。

第15行:呼叫類別Animal的函式show_count。

第16行:呼叫物件a的函式kill。

第17行:呼叫類別Animal的函式show_count。

 (A-11)  靜態方法靜態方法(staticmethod)讓類別不需要建立物件,就可以直接使用該類別的靜態方法,需在類別中函式的前一行使用裝飾器「@staticmethod」。

行號 範例 執行結果 12345 classSay():     @staticmethod     defhello():          print('Hello')Say.hello() Hello   解說第1到4行:定義類別Say,定義靜態函式hello,使用函式print顯示字串「Hello」在螢幕上。

第5行:呼叫類別Animal的靜態函式hello。

 (B) 例外(exception)在執行程式的過程中產生錯誤,程式會中斷執行,發出例外訊息,以下介紹例外的程式區塊,與實作自訂的例外類別。

(B-1) try-except使用程式區塊「try…except…」可以攔截例外,在try區塊中撰寫可能發生錯誤的程式,若發生錯誤,則會跳到except區塊執行進行後續的處理。

行號 範例 執行結果 1234 try:      pwd=input('請輸入密碼')except:      print('發生錯誤') 輸入數字與字元則不會發生錯誤,密碼會儲存在變數pwd,若輸入「ctrl+D」,則顯示「發生錯誤」。

(1)輸入數字與字元 請輸入密碼abc123 (2)輸入「Ctrl+D」 請輸入密碼^D 發生錯誤 解說第1到4行:顯示「請輸入密碼」在螢幕上,使用函式input輸入密碼,將輸入的字串指定給變數pwd,若輸入過程中發生錯誤,例如:輸入「Ctrl+D」,則會跳到except區塊去執行,顯示「發生錯誤」。

(B-2)try-except-else使用程式區塊「try…except…else…」可以攔截例外,在try區塊中撰寫可能發生錯誤的程式,若發生錯誤,則會跳到except區塊進行後續的處理,若沒有發生錯誤,則會跳到else區塊執行。

except後可以接指定錯誤類型,常見錯誤類型,如下表。

錯誤類型 說明 KeyboardInterrupt 當使用者輸入中斷(Ctrl+C)時,發出此錯誤。

ZeroDivisionError 除以0時,發出此錯誤。

EOFError 接受到EOF(endoffile)訊息時,發出此錯誤。

NameError 區域變數或全域變數找不到時,發出此錯誤。

OSError 與作業系統有關的錯誤 FileNotFoundError 檔案或資料夾找不到時,發出此錯誤。

ValueError 輸入資料與程式預期輸入資料型別不同時,發出此錯誤。

  行號 範例 執行結果 123456 try:      pwd=input('請輸入密碼')exceptEOFError:      print('輸入EOF')else:      print('輸入密碼為',pwd) 若輸入「Ctrl+D」,則發出EOFError錯誤,顯示「輸入EOF」;若輸入數字與字元則不會發生錯誤,密碼會儲存在變數pwd,接著執行else區塊顯示「輸入密碼為」接著顯示變數pwd的字串。

(1)輸入數字與字元 請輸入密碼abc123 輸入密碼為abc123 (2)輸入「Ctrl+D」 請輸入密碼^D 輸入EOF 解說第1到6行:顯示「請輸入密碼」在螢幕上,使用函式input輸入密碼,將字串指定給變數pwd(第1到2行)。

若輸入過程中輸入「ctrl+D」,則會跳到exceptEOFError區塊去執行,顯示「輸入EOF」(第3到4行);若沒有發生錯誤,則會跳到else區塊去執行,顯示「輸入密碼為」與變數pwd到螢幕上(第5到6行)。

(B-3)try-except-as-else使用程式區塊「try…except…as…else…」可以攔截例外,在try區塊中撰寫可能發生錯誤的程式,若發生錯誤,則會跳到except區塊進行後續的處理,在except後面接上as就會將錯誤類別轉換成對應的錯誤類別物件,except區塊個數可以有很多個,區分各種錯誤的類型,except區塊內撰寫對應的錯誤處理程式;若沒有發生錯誤,則會跳到else區塊執行。

行號 範例 執行結果 12345678910 try:      num=int(input('請輸入整數'))exceptEOFError:      print('輸入EOF')exceptValueErrorasve:      print('發生ValueError錯誤',ve)exceptExceptionase:      print('發生其他錯誤',e)else:      print('輸入整數為',num) 若輸入「Ctrl+D」,則發出EOFError錯誤,顯示「輸入EOF」;若輸入英文字串則發出ValueError錯誤,命名為ve,顯示「發生ValueError」與錯誤訊息ve;若其他錯誤,則發出Exception錯誤,命名為e,顯示「發生其他錯誤」與錯誤訊息e;若沒有出現錯誤,整數會儲存在變數num,接著執行else區塊顯示「輸入整數為」接著顯示變數num。

(1)輸入數字 請輸入整數123 輸入整數為123 (2)輸入「Ctrl+D」相當於輸入EOF 請輸入整數^D 輸入EOF (3)輸入「abc」 請輸入整數abc 發生ValueError錯誤 invalidliteralforint()withbase10:'abc' 解說第1到10行:顯示「請輸入整數」在螢幕上,使用函式input輸入整數,使用函式int將字串轉換成整數,最後儲存在變數num(第1到2行)。

若輸入過程中輸入「ctrl+D」,則會跳到exceptEOFError區塊去執行,顯示「輸入EOF」(第3到4行);若輸入字串「abc」則會跳到exceptValueErrorasve區塊去執行,顯示「發生ValueError錯誤」與物件ve的訊息(第5到6行);若是其他的錯誤則會跳到except Exceptionase區塊去執行,顯示「發生其他錯誤」與物件e的訊息(第7到8行);若沒有發生錯誤,則會跳到else區塊去執行,顯示「輸入整數為」與變數num到螢幕上(第9到10行)。

(B-4)try-except-as-else與自訂例外類別可以自訂例外類別,自訂例外類別需要繼承系統例外類別Exception,該類別就會成為例外類別,可以傳入參數到自訂例外類別,將錯誤資訊儲存在自訂例外類別,使用指令raise發出例外,接著由except進行例外處理。

行號 範例 123456789101112131415 classPwdException(Exception):      def__init__(self,pwd,len):            super().__init__(self)            self.pwd=pwd            self.len=lentry:      pwd=input('請輸入密碼,長度至少8個字元')      iflen(pwd)<8:            raisePwdException(pwd,len(pwd))exceptEOFError:     print('輸入EOF')exceptPwdExceptionaspex:      print('密碼',pex.pwd,'長度為',pex.len,'密碼長度不足')else:      print('輸入密碼為',pwd)   執行結果 若輸入「Ctrl+D」,則發出EOFError錯誤,顯示「輸入EOF」;若輸入密碼長度小於8,則發出PwdException錯誤,顯示密碼、密碼長度與「密碼長度不足」;若沒有出現錯誤,密碼會儲存在變數pwd,接著執行else區塊顯示「輸入密碼為」接著顯示變數pwd。

以下為三種執行結果。

(1)輸入密碼長度大於等於8個字元 請輸入密碼,長度至少8個字元abcd1234 輸入密碼為 abcd1234 (2)輸入「Ctrl+D」相當於輸入EOF 請輸入密碼,長度至少8個字元^D 輸入EOF (3)輸入「abc」 請輸入密碼,長度至少8個字元abc 密碼abc長度為 3密碼長度不足  解說第1到5行:定義類別PwdException繼承類別Exception,定義函式「__init__」,函式「__init__」輸入參數為self、pwd與len,使用「super()」呼叫基礎類別Exception的函式「__init__」傳入self,設定self.pwd為pwd,設定self.len為len(第2到5行)。

第6到15行:顯示「請輸入密碼,長度至少8個字元」在螢幕上,使用函式input輸入密碼,將密碼指定給變數pwd(第7行)。

若pwd的長度小於8,則發出自訂的例外類別PwdException,輸入參數pwd與pwd的長度(第8到9行);若輸入過程中輸入「ctrl+D」,則會跳到except EOFError區塊去執行,顯示「輸入EOF」(第10到11行);若長度小於8則跳到exceptPwdExceptionaspex區塊去執行,顯示「密碼」串接pex.pwd串接「長度為」串接pex.len串接「密碼長度不足」(第12到13行);若沒有發生錯誤,則會跳到else區塊去執行,顯示「輸入密碼為」與變數pwd到螢幕上(第14到15行)。

 (B-5)try-except-as-else-finally與自訂例外類別使用程式區塊「try…except…as…else…finally…」可以攔截例外,在try區塊中撰寫可能發生錯誤的程式,若發生錯誤,則會跳到except區塊進行後續的處理,在except後面接上as就會將錯誤類別轉換成對應的錯誤類別物件,except區塊個數可以有很多個,區分各種錯誤的類型,except區塊內撰寫對應的錯誤處理程式;若沒有發生錯誤,則會跳到else區塊執行,不管有沒有發生錯誤,最後都要執行finally區塊。

行號 範例 1234567891011121314151617 classPwdException(Exception):      def__init__(self,pwd,len):            super().__init__(self)            self.pwd=pwd            self.len=lentry:      pwd=input('請輸入密碼,長度至少8個字元')      iflen(pwd)<8:             raisePwdException(pwd,len(pwd))exceptEOFError:      print('輸入EOF')exceptPwdExceptionaspex:      print('密碼',pex.pwd,'長度為',pex.len,'密碼長度不足')else:      print('輸入密碼為',pwd)finally:      print('請妥善保管密碼') 執行結果 若輸入「Ctrl+D」,則發出EOFError錯誤,顯示「輸入EOF」;若輸入密碼長度小於8,則發出PwdException錯誤,顯示密碼、密碼長度與「密碼長度不足」;若沒有出現錯誤,密碼會儲存在變數pwd,接著執行else區塊顯示「輸入密碼為」接著顯示變數pwd,最後都會執行finally區塊,顯示「請妥善保管密碼」。

以下為三種執行結果。

(1)輸入密碼長度大於等於8個字元 請輸入密碼,長度至少8個字元abcd1234 輸入密碼為 abcd1234 請妥善保管密碼 (2)輸入「Ctrl+D」相當於輸入EOF 請輸入密碼,長度至少8個字元^D 輸入EOF 請妥善保管密碼 (3)輸入「abc」 請輸入密碼,長度至少8個字元abc 密碼abc長度為 3密碼長度不足 請妥善保管密碼 解說第1到5行:定義類別PwdException繼承類別Exception,定義函式「__init__」,函式「__init__」輸入參數為self、pwd與len,使用「super()」呼叫基礎類別Exception的函式「__init__」傳入self,設定self.pwd為pwd,設定self.len為len(第2到5行)。

第6到17行:顯示「請輸入密碼,長度至少8個字元」在螢幕上,使用函式input輸入密碼,將字串指定給變數pwd(第7行)。

若pwd的長度小於8,則發出自訂的例外類別PwdException,輸入參數pwd與pwd的長度(第8到9行);若輸入過程中輸入「ctrl+D」,則會跳到exceptEOFError區塊去執行,顯示「輸入EOF」(第10到11行);若長度小於8,會跳到exceptPwdExceptionaspex區塊去執行,顯示「密碼」,串接pex.pwd,串接「長度為」,串接pex.len,串接「密碼長度不足」(第12到13行);若沒有發生錯誤,則會跳到else區塊去執行,顯示「輸入密碼為」與變數pwd到螢幕上;最後不管有沒有錯誤,都會執行finally區塊,顯示「請妥善保管密碼」。

  Comments Signin|RecentSiteActivity|ReportAbuse|PrintPage|PoweredByGoogleSites



請為這篇文章評分?